Repository: JetBrains/kotlin-eclipse Branch: master Commit: 202197775219 Files: 1604 Total size: 2.2 MB Directory structure: gitextract_ciuqhpnh/ ├── .gitattributes ├── .github/ │ └── workflows/ │ └── main.yml ├── .gitignore ├── LICENSE ├── README.md ├── common-settings/ │ └── kotlin-formatting.xml ├── docs/ │ └── dev-documentation.md ├── kotlin-bundled-compiler/ │ ├── Get Bundled Kotlin.launch │ ├── META-INF/ │ │ └── MANIFEST.MF │ ├── build.gradle.kts │ ├── build.properties │ ├── buildSrc/ │ │ ├── build.gradle │ │ └── src/ │ │ ├── main/ │ │ │ └── groovy/ │ │ │ └── com/ │ │ │ └── intellij/ │ │ │ └── buildsupport/ │ │ │ ├── dependencies/ │ │ │ │ ├── PackageList.groovy │ │ │ │ ├── PackageListFromManifest.groovy │ │ │ │ └── PackageListFromSimpleFile.groovy │ │ │ ├── resolve/ │ │ │ │ ├── http/ │ │ │ │ │ ├── HttpArtifact.groovy │ │ │ │ │ ├── HttpArtifactsResolver.groovy │ │ │ │ │ └── idea/ │ │ │ │ │ └── IntellijIdeaArtifactsResolver.groovy │ │ │ │ └── tc/ │ │ │ │ ├── TCArtifact.groovy │ │ │ │ ├── TCArtifactsResolver.groovy │ │ │ │ └── kotlin/ │ │ │ │ ├── CommonIDEArtifactsResolver.groovy │ │ │ │ └── KotlinCompilerTCArtifactsResolver.groovy │ │ │ └── utils/ │ │ │ └── FileUtils.groovy │ │ └── test/ │ │ └── groovy/ │ │ └── com/ │ │ └── intellij/ │ │ └── buildsupport/ │ │ └── tc/ │ │ └── kotlin/ │ │ └── KotlinCompilerTCArtifactsResolverSpecification.groovy │ ├── gradle/ │ │ └── wrapper/ │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── pom.xml │ ├── referencedPackages.txt │ └── src/ │ ├── com/ │ │ └── intellij/ │ │ ├── codeInsight/ │ │ │ ├── CodeInsightBundle.java │ │ │ ├── KotlinNullableNotNullManager.kt │ │ │ ├── actions/ │ │ │ │ └── ReformatCodeProcessor.java │ │ │ └── generation/ │ │ │ └── GenerateEqualsHelper.java │ │ ├── formatting/ │ │ │ ├── KotlinLanguageCodeStyleSettingsProvider.kt │ │ │ └── KotlinSettingsProvider.kt │ │ ├── openapi/ │ │ │ ├── editor/ │ │ │ │ └── Editor.java │ │ │ ├── extensions/ │ │ │ │ └── ExtensionException.kt │ │ │ ├── fileTypes/ │ │ │ │ └── StdFileTypes.java │ │ │ └── util/ │ │ │ └── text/ │ │ │ └── StringUtil.java │ │ └── util/ │ │ ├── SequentialModalProgressTask.java │ │ ├── SequentialTask.java │ │ ├── SingletonSet.java │ │ └── containers/ │ │ ├── LinkedMultiMap.java │ │ ├── MultiMap.java │ │ └── ObjectIntHashMap.java │ ├── it/ │ │ └── unimi/ │ │ └── dsi/ │ │ └── fastutil/ │ │ └── ints/ │ │ └── IntOpenHashSet.java │ └── org/ │ └── jetbrains/ │ └── kotlin/ │ └── idea/ │ └── core/ │ └── formatter/ │ └── KotlinPackageEntry.kt ├── kotlin-eclipse-aspects/ │ ├── META-INF/ │ │ ├── MANIFEST.MF │ │ └── aop.xml │ ├── build.properties │ ├── pom.xml │ └── src/ │ └── org/ │ └── jetbrains/ │ └── kotlin/ │ └── aspects/ │ ├── Activator.java │ ├── debug/ │ │ ├── core/ │ │ │ ├── KotlinSourceLookupAspect.aj │ │ │ └── KotlinStackFrameFilterAspect.aj │ │ └── ui/ │ │ └── SuppressBreakpointMarkerUpdaterAspect.aj │ ├── navigation/ │ │ ├── KotlinFindSourceAspect.aj │ │ ├── KotlinOpenEditorAspect.aj │ │ └── KotlinSearchEditorOpenerAspect.aj │ ├── refactoring/ │ │ ├── KotlinBinaryReferencesAspect.aj │ │ ├── KotlinBreakpointRenamingParticipantAspect.aj │ │ ├── KotlinJavaDescriptorAspect.aj │ │ ├── KotlinRefactoringChecksAspect.aj │ │ ├── KotlinRefactoringTypeAspect.aj │ │ ├── KotlinRemoveDeclarationUpdateAspect.aj │ │ ├── KotlinRenameFromJavaAspect.aj │ │ └── KotlinRippleMethodFinderAspect.aj │ └── ui/ │ └── PackageExplorerLabelProviderAspect.aj ├── kotlin-eclipse-core/ │ ├── META-INF/ │ │ └── MANIFEST.MF │ ├── build.properties │ ├── plugin.xml │ ├── pom.xml │ ├── preferences.ini │ ├── schema/ │ │ ├── org.jetbrains.kotlin.core.predefinedKotlinCodeStyle.exsd │ │ └── org.jetbrains.kotlin.core.scriptTemplateContribution.exsd │ └── src/ │ └── org/ │ └── jetbrains/ │ └── kotlin/ │ └── core/ │ ├── Activator.java │ ├── KotlinClasspathContainer.kt │ ├── KotlinClasspathContainerInitializer.kt │ ├── KotlinClasspathProvider.kt │ ├── asJava/ │ │ ├── BinaryClassWriter.java │ │ ├── KotlinLightClassGeneration.kt │ │ ├── LightClassBuilderFactory.java │ │ ├── LightClassFile.java │ │ └── elementUtils.kt │ ├── builder/ │ │ └── KotlinPsiManager.kt │ ├── compiler/ │ │ ├── KotlinCompiler.kt │ │ ├── KotlinCompiler2.java │ │ └── KotlinCompilerUtils.kt │ ├── debug/ │ │ └── KotlinSourceLookupNavigator.java │ ├── filesystem/ │ │ ├── EnvironmentRemnantNature.kt │ │ ├── KotlinFileStore.kt │ │ ├── KotlinFileSystem.java │ │ ├── KotlinLightClassManager.kt │ │ └── KotlinScriptFIleSystem.kt │ ├── formatting/ │ │ └── KotlinCodeStyleManager.kt │ ├── imports/ │ │ ├── FunctionImportFinder.kt │ │ ├── importCandidates.kt │ │ └── importServices.kt │ ├── launch/ │ │ ├── CompilerOutputData.java │ │ ├── CompilerOutputElement.java │ │ ├── CompilerOutputParser.java │ │ └── KotlinCLICompiler.kt │ ├── log/ │ │ └── kotlinLogger.kt │ ├── model/ │ │ ├── CachedEnvironment.kt │ │ ├── DummyCodeStyleManager.kt │ │ ├── EclipseKotlinModuleResolver.kt │ │ ├── EclipseScriptDefinitionProvider.kt │ │ ├── KotlinAnalysisFileCache.kt │ │ ├── KotlinAnalysisProjectCache.kt │ │ ├── KotlinCommonEnvironment.kt │ │ ├── KotlinEnvironment.kt │ │ ├── KotlinJavaManager.kt │ │ ├── KotlinLightVirtualFile.kt │ │ ├── KotlinNature.kt │ │ ├── KotlinRefreshProjectListener.kt │ │ ├── executableEP.kt │ │ └── kotlinModelUtils.kt │ ├── preferences/ │ │ ├── KotlinBuildingProperties.kt │ │ ├── KotlinCodeStyleProperties.kt │ │ ├── KotlinProperties.kt │ │ ├── KotlinPropertiesExtensions.kt │ │ └── Preferences.kt │ ├── references/ │ │ ├── KotlinReference.kt │ │ └── referenceUtils.kt │ ├── resolve/ │ │ ├── BuiltInsReferenceResolver.java │ │ ├── DeserializedDescriptorUtils.kt │ │ ├── EclipseAnalyzerFacadeForJVM.kt │ │ ├── EclipseDescriptorUtils.java │ │ ├── KotlinAnalyzer.kt │ │ ├── KotlinCacheServiceImpl.kt │ │ ├── KotlinPackagePartProvider.kt │ │ ├── KotlinResolutionFacade.kt │ │ ├── KotlinSourceIndex.java │ │ ├── injection.kt │ │ ├── lang/ │ │ │ ├── java/ │ │ │ │ ├── EclipseJavaClassFinder.java │ │ │ │ ├── resolver/ │ │ │ │ │ ├── EclipseJavaSourceElement.java │ │ │ │ │ ├── EclipseJavaSourceElementFactory.java │ │ │ │ │ └── EclipseTraceBasedJavaResolverCache.kt │ │ │ │ └── structure/ │ │ │ │ ├── EclipseJavaAnnotation.kt │ │ │ │ ├── EclipseJavaAnnotationArgument.kt │ │ │ │ ├── EclipseJavaAnnotationAsAnnotationArgument.kt │ │ │ │ ├── EclipseJavaArrayAnnotationArgument.kt │ │ │ │ ├── EclipseJavaArrayType.java │ │ │ │ ├── EclipseJavaClass.kt │ │ │ │ ├── EclipseJavaClassObjectAnnotationArgument.java │ │ │ │ ├── EclipseJavaClassifier.kt │ │ │ │ ├── EclipseJavaClassifierType.java │ │ │ │ ├── EclipseJavaConstructor.java │ │ │ │ ├── EclipseJavaElement.kt │ │ │ │ ├── EclipseJavaElementFactory.java │ │ │ │ ├── EclipseJavaElementUtil.java │ │ │ │ ├── EclipseJavaField.kt │ │ │ │ ├── EclipseJavaLiteralAnnotationArgument.java │ │ │ │ ├── EclipseJavaMember.java │ │ │ │ ├── EclipseJavaMethod.kt │ │ │ │ ├── EclipseJavaPackage.java │ │ │ │ ├── EclipseJavaPrimitiveType.java │ │ │ │ ├── EclipseJavaPropertyInitializerEvaluator.java │ │ │ │ ├── EclipseJavaReferenceAnnotationArgument.java │ │ │ │ ├── EclipseJavaType.java │ │ │ │ ├── EclipseJavaTypeAsAnnotationArgument.kt │ │ │ │ ├── EclipseJavaTypeParameter.kt │ │ │ │ ├── EclipseJavaValueParameter.java │ │ │ │ ├── EclipseJavaWildcardType.java │ │ │ │ └── EclipseOptimizedJavaClass.kt │ │ │ └── kotlin/ │ │ │ └── EclipseVirtualFileFinder.kt │ │ └── sources/ │ │ └── LibrarySourcesIndex.kt │ ├── script/ │ │ ├── EnvironmentProjectsManager.kt │ │ ├── ScriptTemplateContribution.kt │ │ └── template/ │ │ ├── ProjectFilesResolver.kt │ │ ├── ProjectScriptTemplate.kt │ │ └── ProjectScriptTemplateContribution.kt │ └── utils/ │ ├── DebugUtils.java │ ├── DependencyResolverException.kt │ ├── ProjectUtils.kt │ ├── analyzeUtils.kt │ ├── genericUtils.kt │ ├── importsUtils.kt │ ├── jobUtils.kt │ ├── kotlinFilesCollectorUtils.kt │ └── projectFilesUtils.kt ├── kotlin-eclipse-feature/ │ ├── build.properties │ ├── feature.xml │ └── pom.xml ├── kotlin-eclipse-gradle/ │ ├── META-INF/ │ │ └── MANIFEST.MF │ ├── build.properties │ ├── plugin.xml │ ├── pom.xml │ ├── scripts/ │ │ └── init.gradle.kts │ └── src/ │ └── org/ │ └── jetbrains/ │ └── kotlin/ │ └── gradle/ │ ├── Activator.kt │ ├── configurator/ │ │ └── KotlinProjectConfigurator.kt │ └── initialization/ │ └── ModelInjector.kt ├── kotlin-eclipse-gradle-feature/ │ ├── build.properties │ ├── feature.xml │ └── pom.xml ├── kotlin-eclipse-gradle-model/ │ ├── META-INF/ │ │ └── MANIFEST.MF │ ├── build.gradle │ ├── build.properties │ ├── gradle/ │ │ └── wrapper/ │ │ ├── gradle-wrapper.jar │ │ └── gradle-wrapper.properties │ ├── gradlew │ ├── gradlew.bat │ ├── pom.xml │ ├── settings.gradle │ └── src/ │ └── org/ │ └── jetbrains/ │ └── kotlin/ │ └── gradle/ │ └── model/ │ ├── GradleMultiProjectForEclipse.kt │ ├── GradleProjectForEclipse.kt │ └── plugins.kt ├── kotlin-eclipse-maven/ │ ├── META-INF/ │ │ └── MANIFEST.MF │ ├── build.properties │ ├── lifecycle-mapping-metadata.xml │ ├── plugin.xml │ ├── pom.xml │ └── src/ │ └── org/ │ └── jetbrains/ │ └── kotlin/ │ └── maven/ │ ├── Activator.java │ └── configuration/ │ ├── KotlinMavenProjectConfigurator.kt │ └── MavenAttributeAccessor.kt ├── kotlin-eclipse-p2updatesite/ │ ├── category.xml │ └── pom.xml ├── kotlin-eclipse-policy/ │ ├── build.properties │ ├── feature.xml │ └── pom.xml ├── kotlin-eclipse-test-framework/ │ ├── META-INF/ │ │ └── MANIFEST.MF │ ├── build.properties │ ├── pom.xml │ └── src/ │ └── org/ │ └── jetbrains/ │ └── kotlin/ │ └── testframework/ │ ├── Activator.java │ ├── editor/ │ │ ├── KotlinEditorAutoTestCase.java │ │ ├── KotlinEditorSequentialAutoTestCase.java │ │ ├── KotlinEditorTestCase.java │ │ ├── KotlinEditorWithAfterFileTestCase.java │ │ ├── KotlinProjectTestCase.java │ │ └── TextEditorTest.java │ └── utils/ │ ├── CodeStyleConfigurator.kt │ ├── EditorTestUtils.java │ ├── ExpectedCompletionUtils.java │ ├── InTextDirectivesUtils.java │ ├── KotlinTestUtils.java │ ├── SourceFileData.java │ ├── TestJavaProject.java │ ├── TypingUtils.java │ └── WorkspaceUtil.java ├── kotlin-eclipse-ui/ │ ├── META-INF/ │ │ └── MANIFEST.MF │ ├── Run Kotlin Plugin with Equinox Weaving.launch │ ├── Run with open port.launch │ ├── build.properties │ ├── plugin.xml │ ├── pom.xml │ ├── schema/ │ │ └── org.jetbrains.kotlin.ui.editor.textHover.exsd │ ├── src/ │ │ └── org/ │ │ └── jetbrains/ │ │ └── kotlin/ │ │ ├── eclipse/ │ │ │ └── ui/ │ │ │ └── utils/ │ │ │ ├── EditorUtil.java │ │ │ ├── IndenterUtil.java │ │ │ ├── KotlinEclipseScope.kt │ │ │ ├── KotlinImageProvider.kt │ │ │ ├── LineEndUtil.java │ │ │ ├── ProjectScopedPreferenceUtils.java │ │ │ ├── analyzeUtils.kt │ │ │ └── offsetUtils.kt │ │ ├── perspective/ │ │ │ └── KotlinPerspectiveFactory.java │ │ ├── preferences/ │ │ │ ├── BasePropertyPage.kt │ │ │ ├── EditorPreferencePage.java │ │ │ ├── KotlinPreferenceInitializer.kt │ │ │ ├── KotlinPreferencePage.java │ │ │ ├── KotlinTemplatePreferencePage.java │ │ │ ├── building/ │ │ │ │ ├── ProjectBuildingPropertyPage.kt │ │ │ │ └── WorkspaceBuildingPropertyPage.kt │ │ │ ├── compiler/ │ │ │ │ ├── CompilerPluginDialog.kt │ │ │ │ ├── ProjectCompilerPropertyPage.kt │ │ │ │ ├── RebuildJob.kt │ │ │ │ └── WorkspaceCompilerPropertyPage.kt │ │ │ ├── style/ │ │ │ │ ├── ProjectCodeStylePropertyPage.kt │ │ │ │ └── WorkspaceCodeStylePropertyPage.kt │ │ │ └── views/ │ │ │ ├── BuildingPropertiesView.kt │ │ │ ├── CompilerPropertiesView.kt │ │ │ ├── ProjectCompilerPropertiesView.kt │ │ │ ├── Validable.kt │ │ │ └── codeStylePropertiesView.kt │ │ ├── swt/ │ │ │ └── builders/ │ │ │ ├── ChecklistView.kt │ │ │ └── controls.kt │ │ ├── ui/ │ │ │ ├── Activator.kt │ │ │ ├── KotlinAwarePackageExplorerLabelProvider.kt │ │ │ ├── KotlinPluginUpdater.kt │ │ │ ├── KotlinUiStartupClass.java │ │ │ ├── RemoveRemnantProjectsJob.kt │ │ │ ├── ScriptClasspathUpdater.kt │ │ │ ├── ScriptEnvironmentsFilter.kt │ │ │ ├── builder/ │ │ │ │ ├── AspectsUtils.java │ │ │ │ ├── BaseKotlinBuilderElement.kt │ │ │ │ ├── CompileKotlinClassesAction.kt │ │ │ │ ├── IncrementalKotlinBuilderElement.kt │ │ │ │ ├── KotlinAnalysisJob.kt │ │ │ │ ├── KotlinBuilder.kt │ │ │ │ ├── KotlinBuilderElement.kt │ │ │ │ ├── ResourceChangeListener.kt │ │ │ │ └── kotlinJavaElementsListeners.kt │ │ │ ├── commands/ │ │ │ │ ├── AddCoroutinesActionHandler.kt │ │ │ │ ├── ConfigureKotlinActionHandler.kt │ │ │ │ ├── DeconfigureKotlinActionHandler.kt │ │ │ │ ├── commandsUtils.kt │ │ │ │ ├── findReferences/ │ │ │ │ │ ├── KotlinFindReferencesAction.kt │ │ │ │ │ └── querySpecifications.kt │ │ │ │ ├── j2k/ │ │ │ │ │ ├── CompositeUndoableOperation.java │ │ │ │ │ ├── JavaToKotlinActionHandler.java │ │ │ │ │ ├── SetFileCharsetOperation.java │ │ │ │ │ └── converterUtils.kt │ │ │ │ └── psiVisualization/ │ │ │ │ ├── PsiContentProvider.java │ │ │ │ ├── PsiVisualization.java │ │ │ │ └── VisualizationPage.java │ │ │ ├── debug/ │ │ │ │ ├── KotlinRunToLineAdapter.kt │ │ │ │ ├── KotlinToggleBreakpointAdapter.kt │ │ │ │ └── commands/ │ │ │ │ └── KotlinStepIntoSelectionHandler.kt │ │ │ ├── editors/ │ │ │ │ ├── Configuration.java │ │ │ │ ├── FileEditorConfiguration.kt │ │ │ │ ├── KotlinActionGroup.kt │ │ │ │ ├── KotlinAutoIndentStrategy.java │ │ │ │ ├── KotlinBracketInserter.java │ │ │ │ ├── KotlinClassFileEditor.kt │ │ │ │ ├── KotlinClassFileEditorInput.kt │ │ │ │ ├── KotlinCommonEditor.kt │ │ │ │ ├── KotlinCorrectionProcessor.kt │ │ │ │ ├── KotlinEditor.kt │ │ │ │ ├── KotlinElementHyperlink.kt │ │ │ │ ├── KotlinElementHyperlinkDetector.kt │ │ │ │ ├── KotlinFileEditor.kt │ │ │ │ ├── KotlinFormatAction.kt │ │ │ │ ├── KotlinReconcilingStrategy.kt │ │ │ │ ├── KotlinScriptEditor.kt │ │ │ │ ├── annotations/ │ │ │ │ │ ├── AnnotationManager.kt │ │ │ │ │ ├── DiagnosticAnnotation.kt │ │ │ │ │ ├── DiagnosticAnnotationUtil.java │ │ │ │ │ └── KotlinAnnotationImageProvider.java │ │ │ │ ├── codeassist/ │ │ │ │ │ ├── CompletionElementType.kt │ │ │ │ │ ├── FilterPositionUtil.java │ │ │ │ │ ├── KeywordCompletion.kt │ │ │ │ │ ├── KotlinCompletionProcessor.kt │ │ │ │ │ ├── KotlinCompletionProposal.kt │ │ │ │ │ ├── KotlinContextInfoContentAssistProcessor.kt │ │ │ │ │ ├── KotlinFunctionCompletionProposal.kt │ │ │ │ │ ├── KotlinFunctionParameterInfoAssist.kt │ │ │ │ │ ├── KotlinParameterListValidator.kt │ │ │ │ │ ├── VisibilityUtils.kt │ │ │ │ │ ├── nonImportedCompletionHandler.kt │ │ │ │ │ ├── positionFilters.kt │ │ │ │ │ └── relevanceSorting.kt │ │ │ │ ├── completion/ │ │ │ │ │ ├── KotlinCompletionUtils.kt │ │ │ │ │ └── KotlinReferenceVariantsHelper.kt │ │ │ │ ├── highlighting/ │ │ │ │ │ ├── KotlinHighlightingColors.kt │ │ │ │ │ ├── KotlinPositionUpdater.kt │ │ │ │ │ ├── KotlinSemanticHighlighting.kt │ │ │ │ │ ├── KotlinSemanticHighlightingVisitor.kt │ │ │ │ │ ├── KotlinTokenScanner.java │ │ │ │ │ ├── KotlinTokens.kt │ │ │ │ │ └── KotlinViewerCreator.kt │ │ │ │ ├── hover/ │ │ │ │ │ ├── KotlinInformationProvider.kt │ │ │ │ │ ├── KotlinJavadocTextHover.kt │ │ │ │ │ ├── KotlinProblemTextHover.kt │ │ │ │ │ └── KotlinTextHover.kt │ │ │ │ ├── navigation/ │ │ │ │ │ ├── JarNavigationUtils.kt │ │ │ │ │ ├── KotlinOpenDeclarationAction.kt │ │ │ │ │ ├── KotlinOpenEditorFromConsole.kt │ │ │ │ │ ├── KotlinOpenSuperImplementationAction.kt │ │ │ │ │ ├── StringInput.kt │ │ │ │ │ ├── StringStorage.kt │ │ │ │ │ ├── navigationUtils.kt │ │ │ │ │ └── psiDeclarationFinder.kt │ │ │ │ ├── occurrences/ │ │ │ │ │ └── KotlinMarkOccurrences.kt │ │ │ │ ├── organizeImports/ │ │ │ │ │ ├── KotlinOrganizeImportsAction.kt │ │ │ │ │ └── importsCollector.kt │ │ │ │ ├── outline/ │ │ │ │ │ ├── KotlinOutlinePage.kt │ │ │ │ │ ├── KotlinOutlinePopup.java │ │ │ │ │ ├── PsiContentProvider.kt │ │ │ │ │ └── PsiLabelProvider.java │ │ │ │ ├── quickassist/ │ │ │ │ │ ├── KotlinChangeReturnTypeProposal.kt │ │ │ │ │ ├── KotlinConvertToBlockBodyAssistProposal.kt │ │ │ │ │ ├── KotlinConvertToExpressionBodyAssistProposal.kt │ │ │ │ │ ├── KotlinImplementMethodsProposal.kt │ │ │ │ │ ├── KotlinIntentionUtils.kt │ │ │ │ │ ├── KotlinQuickAssist.kt │ │ │ │ │ ├── KotlinQuickAssistProcessor.kt │ │ │ │ │ ├── KotlinQuickAssistProposal.kt │ │ │ │ │ ├── KotlinQuickAssistProposalsGenerator.kt │ │ │ │ │ ├── KotlinRemoveExplicitTypeAssistProposal.kt │ │ │ │ │ ├── KotlinReplaceGetAssistProposal.java │ │ │ │ │ └── KotlinSpecifyTypeAssistProposal.kt │ │ │ │ ├── quickfix/ │ │ │ │ │ ├── KotlinAddModifierResolution.kt │ │ │ │ │ ├── KotlinAutoImportQuickFix.kt │ │ │ │ │ ├── KotlinMakeOverridenMemberOpenResolution.kt │ │ │ │ │ ├── KotlinMarkerResolutionGenerator.kt │ │ │ │ │ ├── KotlinQuickFix.kt │ │ │ │ │ ├── KotlinRemoveModifierResolution.kt │ │ │ │ │ └── MarkerExtensions.kt │ │ │ │ ├── selection/ │ │ │ │ │ ├── KotlinSelectEnclosingAction.java │ │ │ │ │ ├── KotlinSelectNextAction.java │ │ │ │ │ ├── KotlinSelectPreviousAction.java │ │ │ │ │ ├── KotlinSemanticSelectionAction.java │ │ │ │ │ ├── PsiElementChildrenIterable.java │ │ │ │ │ └── handlers/ │ │ │ │ │ ├── KotlinBlockSelectionHandler.kt │ │ │ │ │ ├── KotlinDeclarationSelectionHandler.kt │ │ │ │ │ ├── KotlinDefaultSelectionHandler.kt │ │ │ │ │ ├── KotlinDocSectionSelectionHandler.kt │ │ │ │ │ ├── KotlinElementSelectionHandler.java │ │ │ │ │ ├── KotlinElementSelectioner.kt │ │ │ │ │ ├── KotlinListSelectionHandler.kt │ │ │ │ │ ├── KotlinNonTraversableSelectionHanlder.kt │ │ │ │ │ ├── KotlinStringTemplateSelectionHandler.kt │ │ │ │ │ ├── KotlinWhiteSpaceSelectionHandler.kt │ │ │ │ │ └── PsiUtils.kt │ │ │ │ └── templates/ │ │ │ │ ├── KotlinApplicableTemplateContext.java │ │ │ │ ├── KotlinDocumentTemplateContext.java │ │ │ │ ├── KotlinTemplateContextType.java │ │ │ │ ├── KotlinTemplateFormatter.java │ │ │ │ └── KotlinTemplateManager.java │ │ │ ├── formatter/ │ │ │ │ ├── AbstractBlock.kt │ │ │ │ ├── AlignmentStrategy.java │ │ │ │ ├── AlignmentStrategy.kt │ │ │ │ ├── EclipseDocumentFormattingModel.java │ │ │ │ ├── EclipseFormattingModel.java │ │ │ │ ├── KotlinBlock.kt │ │ │ │ ├── NodeAlignmentStrategy.kt │ │ │ │ └── kotlinFormatter.kt │ │ │ ├── launch/ │ │ │ │ ├── CompilerStatusHandler.kt │ │ │ │ ├── KotlinLaunchShortcut.kt │ │ │ │ ├── KotlinLaunchableTester.kt │ │ │ │ ├── KotlinRuntimeConfigurator.kt │ │ │ │ ├── KotlinScriptLaunchConfigurationDelegate.kt │ │ │ │ ├── KotlinScriptLaunchConfigurationTabGroup.kt │ │ │ │ ├── KotlinScriptLaunchShortcut.kt │ │ │ │ ├── KotlinScriptLaunchableTester.kt │ │ │ │ ├── junit/ │ │ │ │ │ ├── KotlinJUnitLaunchShortcut.java │ │ │ │ │ ├── KotlinJUnitLaunchUtils.java │ │ │ │ │ └── KotlinJUnitLaunchableTester.java │ │ │ │ └── kotlinConsole.kt │ │ │ ├── navigation/ │ │ │ │ ├── KotlinOpenEditor.java │ │ │ │ └── KotlinOpenEditorUtils.kt │ │ │ ├── overrideImplement/ │ │ │ │ ├── KotlinCallableLabelProvider.kt │ │ │ │ └── KotlinOverrideMembersAction.kt │ │ │ ├── refactorings/ │ │ │ │ ├── extract/ │ │ │ │ │ ├── KotlinExtractVariableAction.kt │ │ │ │ │ ├── KotlinExtractVariableRefactoring.kt │ │ │ │ │ └── KotlinExtractVariableWizard.kt │ │ │ │ └── rename/ │ │ │ │ ├── KotlinLightElementsFactory.java │ │ │ │ ├── KotlinRenameAction.kt │ │ │ │ ├── KotlinRenameParticipant.kt │ │ │ │ ├── KotlinRenameProcessor.kt │ │ │ │ ├── lightEclipseElements.kt │ │ │ │ ├── refactoringUtils.kt │ │ │ │ └── renameParticipants.kt │ │ │ └── search/ │ │ │ ├── KotlinElementMatchCreator.kt │ │ │ ├── KotlinQueryParticipant.kt │ │ │ ├── KotlinReferenceMatchPresentation.kt │ │ │ ├── SearchParentObjectMapper.kt │ │ │ └── searchFilters.kt │ │ ├── utils/ │ │ │ ├── DescriptorUtils.kt │ │ │ ├── LazyObservable.kt │ │ │ └── ThrowableExtensions.kt │ │ └── wizards/ │ │ ├── AbstractWizard.java │ │ ├── AbstractWizardPage.java │ │ ├── FileCreationOp.java │ │ ├── NewProjectWizard.java │ │ ├── NewProjectWizardPage.java │ │ ├── NewUnitWizard.java │ │ ├── NewUnitWizardPage.java │ │ ├── ProjectCreationOp.java │ │ ├── SWTWizardUtils.java │ │ ├── WizardType.kt │ │ ├── unitWizards.kt │ │ └── wizardUtils.kt │ └── templates/ │ └── default-templates.xml ├── kotlin-eclipse-ui-test/ │ ├── META-INF/ │ │ └── MANIFEST.MF │ ├── build.properties │ ├── plugin.xml │ ├── pom.xml │ ├── src/ │ │ └── org/ │ │ └── jetbrains/ │ │ └── kotlin/ │ │ ├── checkers/ │ │ │ └── KotlinDiagnosticsTestCase.java │ │ ├── core/ │ │ │ └── tests/ │ │ │ ├── diagnostics/ │ │ │ │ ├── AdditionalConditions.java │ │ │ │ ├── AllDiagnosticsTests.java │ │ │ │ ├── FileComparisonFailure.java │ │ │ │ ├── JavaAnnotationArgumentsInKotlinTest.java │ │ │ │ ├── JetLightFixture.java │ │ │ │ ├── JetTestUtils.java │ │ │ │ ├── KotlinDiagnosticsJavaPlusKotlinTest.java │ │ │ │ └── KotlinDiagnosticsTest.java │ │ │ └── launch/ │ │ │ ├── AllTests.java │ │ │ ├── KotlinJUnitLaunchTest.java │ │ │ ├── KotlinJUnitLaunchTestCase.java │ │ │ ├── KotlinLaunchTest.java │ │ │ └── KotlinLaunchTestCase.kt │ │ └── ui/ │ │ ├── AllTests.java │ │ └── tests/ │ │ ├── editors/ │ │ │ ├── AllTests.java │ │ │ ├── CommandTestCase.java │ │ │ ├── KotlinAnalyzerInIDETest.java │ │ │ ├── KotlinAnalyzerInIDETestCase.kt │ │ │ ├── KotlinAutoIndentTest.java │ │ │ ├── KotlinAutoIndentTestCase.kt │ │ │ ├── KotlinAutoIndenterTestCase.java │ │ │ ├── KotlinBasicAutoIndentTest.java │ │ │ ├── KotlinBracketInserterTest.java │ │ │ ├── KotlinBracketInserterTestCase.java │ │ │ ├── KotlinCustomLocationBugTest.java │ │ │ ├── KotlinEditorBaseTest.java │ │ │ ├── KotlinEditorClosedProjectInfluenceTest.java │ │ │ ├── PsiVisualizationCommandTest.java │ │ │ ├── completion/ │ │ │ │ ├── AllTests.java │ │ │ │ ├── KotlinBasicCompletionTest.java │ │ │ │ ├── KotlinBasicCompletionTestCase.kt │ │ │ │ ├── KotlinCompletionRelevanceTest.java │ │ │ │ ├── KotlinCompletionRelevanceTestCase.kt │ │ │ │ ├── KotlinFunctionParameterInfoTest.java │ │ │ │ ├── KotlinFunctionParameterInfoTestCase.kt │ │ │ │ ├── KotlinKeywordCompletionTest.java │ │ │ │ ├── KotlinKeywordCompletionTestCase.kt │ │ │ │ ├── completionTestUtils.kt │ │ │ │ ├── handlers/ │ │ │ │ │ ├── KotlinCompletionHandlerInsertTest.java │ │ │ │ │ └── KotlinCompletionHandlerInsertTestCase.java │ │ │ │ └── templates/ │ │ │ │ ├── AllTests.java │ │ │ │ ├── KotlinTemplatesTest.java │ │ │ │ └── KotlinTemplatesTestCase.java │ │ │ ├── formatter/ │ │ │ │ ├── AllFormatTests.java │ │ │ │ ├── KotlinFileAnnotationsFormatTest.java │ │ │ │ ├── KotlinFormatActionTest.java │ │ │ │ ├── KotlinFormatActionTestCase.java │ │ │ │ ├── KotlinIdeaFormatActionTest.java │ │ │ │ ├── KotlinModifierListFormatTest.java │ │ │ │ └── KotlinParameterListFormatTest.java │ │ │ ├── highlighting/ │ │ │ │ ├── KotlinHighlightingPositionUpdaterTest.java │ │ │ │ ├── KotlinHighlightingPositionUpdaterTestCase.kt │ │ │ │ ├── KotlinHighlightingTest.java │ │ │ │ └── KotlinHighlightingTestCase.java │ │ │ ├── markers/ │ │ │ │ ├── AllTests.java │ │ │ │ ├── KotlinParsingMarkersTest.java │ │ │ │ ├── KotlinParsingMarkersTestCase.java │ │ │ │ └── MarkerAttributesTest.java │ │ │ ├── navigation/ │ │ │ │ ├── AllTests.java │ │ │ │ ├── JavaToKotlinNavigationTest.java │ │ │ │ ├── JavaToKotlinNavigationTestCase.java │ │ │ │ ├── KotlinBuiltInsReferenceResolverTest.java │ │ │ │ ├── KotlinBuiltInsReferenceResolverTestCase.java │ │ │ │ ├── KotlinNavigationFromLibraryTest.java │ │ │ │ ├── KotlinNavigationFromLibraryTestCase.kt │ │ │ │ ├── KotlinNavigationTest.java │ │ │ │ ├── KotlinNavigationTestCase.java │ │ │ │ ├── KotlinNavigationToLibraryTest.java │ │ │ │ ├── KotlinNavigationToLibraryTestCase.kt │ │ │ │ ├── KotlinNavigationToSuperTest.java │ │ │ │ ├── KotlinNavigationToSuperTestCase.kt │ │ │ │ ├── KotlinSourcesNavigationTestCase.kt │ │ │ │ └── library/ │ │ │ │ └── NavigationTestLibrary.kt │ │ │ ├── organizeImports/ │ │ │ │ ├── KotlinCommonOptimizeImportsTest.java │ │ │ │ ├── KotlinJvmOptimizeImportsTest.java │ │ │ │ ├── KotlinOrganizeImportsTest.java │ │ │ │ └── KotlinOrganizeImportsTestCase.kt │ │ │ ├── quickfix/ │ │ │ │ ├── autoimport/ │ │ │ │ │ ├── AllTests.java │ │ │ │ │ ├── KotlinAbstractModifierQuickFixTest.java │ │ │ │ │ ├── KotlinAutoImportTest.java │ │ │ │ │ ├── KotlinAutoImportTestCase.java │ │ │ │ │ ├── KotlinChangeModifiersQuickFixTest.java │ │ │ │ │ ├── KotlinMakeClassOpenQuickFixTest.java │ │ │ │ │ ├── KotlinMakeOverridenMemberOpenQuickFixTest.java │ │ │ │ │ └── KotlinQuickFixTestCase.kt │ │ │ │ └── intentions/ │ │ │ │ ├── AbstractKotlinQuickAssistTestCase.java │ │ │ │ ├── KotlinChangeReturnTypeTest.java │ │ │ │ ├── KotlinChangeReturnTypeTestCase.kt │ │ │ │ ├── KotlinConvertToBlockBodyTest.java │ │ │ │ ├── KotlinConvertToBlockBodyTestCase.java │ │ │ │ ├── KotlinConvertToExpressionBodyTest.java │ │ │ │ ├── KotlinConvertToExpressionBodyTestCase.java │ │ │ │ ├── KotlinImplementMethodsTest.java │ │ │ │ ├── KotlinImplementMethodsTestCase.java │ │ │ │ ├── KotlinOverrideMembersTestCase.kt │ │ │ │ ├── KotlinOverrideMethodsTest.java │ │ │ │ ├── KotlinRemoveExplicitTypeTest.java │ │ │ │ ├── KotlinRemoveExplicitTypeTestCase.kt │ │ │ │ ├── KotlinReplaceGetIntentionTest.java │ │ │ │ ├── KotlinReplaceGetIntentionTestCase.java │ │ │ │ ├── KotlinSpacesForTabsQuickAssistTestCase.java │ │ │ │ ├── KotlinSpecifyTypeTest.java │ │ │ │ └── KotlinSpecifyTypeTestCase.java │ │ │ └── selection/ │ │ │ ├── KotlinCommonSelectionTestCase.kt │ │ │ ├── KotlinSelectEnclosingTest.java │ │ │ ├── KotlinSelectEnclosingTestCase.kt │ │ │ ├── KotlinSelectNextTest.java │ │ │ ├── KotlinSelectNextTestCase.kt │ │ │ ├── KotlinSelectPreviousTest.java │ │ │ └── KotlinSelectPreviousTestCase.kt │ │ ├── refactoring/ │ │ │ ├── convert/ │ │ │ │ └── JavaToKotlinEncodingBugTest.java │ │ │ ├── extract/ │ │ │ │ ├── KotlinExtractVariableTest.java │ │ │ │ └── KotlinExtractVariableTestCase.kt │ │ │ └── rename/ │ │ │ ├── KotlinLocalRenameTest.java │ │ │ ├── KotlinLocalRenameTestCase.kt │ │ │ ├── KotlinRenameTest.java │ │ │ └── KotlinRenameTestCase.kt │ │ ├── scripts/ │ │ │ ├── completion/ │ │ │ │ └── CompletionInScriptsTest.java │ │ │ ├── navigation/ │ │ │ │ └── BasicNavigationInScripts.java │ │ │ └── templates/ │ │ │ ├── KotlinScriptWithTemplateResolveTest.java │ │ │ ├── KotlinScriptWithTemplateResolveTestCase.kt │ │ │ ├── TestKtScriptTemplateProvider.kt │ │ │ ├── TestKtScriptTemplateProviderEx.kt │ │ │ ├── TestScriptTemplateDefinition.kt │ │ │ └── testCustomEPResolver.kt │ │ └── search/ │ │ ├── KotlinFindReferencesTest.java │ │ └── KotlinFindReferencesTestCase.kt │ └── testData/ │ ├── compiler/ │ │ └── diagnostics/ │ │ └── tests/ │ │ ├── ResolveOfJavaGenerics.kt │ │ ├── ResolveOfJavaGenerics.txt │ │ ├── ResolveToJava.kt │ │ ├── ResolveToJava.txt │ │ ├── StarsInFunctionCalls.kt │ │ ├── StarsInFunctionCalls.txt │ │ ├── TypeInference.kt │ │ └── TypeInference.txt │ ├── completion/ │ │ ├── autoimport/ │ │ │ ├── classNestedInClassImport/ │ │ │ │ ├── dependency.kt │ │ │ │ ├── test.kt │ │ │ │ └── test.kt.after │ │ │ ├── classNestedInObjectImport/ │ │ │ │ ├── dependency.kt │ │ │ │ ├── test.kt │ │ │ │ └── test.kt.after │ │ │ ├── extensionFunctionImport/ │ │ │ │ ├── dependency.kt │ │ │ │ ├── other.kt │ │ │ │ ├── test.kt │ │ │ │ └── test.kt.after │ │ │ ├── extensionFunctionReferenceImport/ │ │ │ │ ├── dependency.kt │ │ │ │ ├── other.kt │ │ │ │ ├── test.kt │ │ │ │ └── test.kt.after │ │ │ ├── extensionInfixFunctionImport/ │ │ │ │ ├── dependency.kt │ │ │ │ ├── other1.kt │ │ │ │ ├── other2.kt │ │ │ │ ├── test.kt │ │ │ │ └── test.kt.after │ │ │ ├── extensionMethodInLambdaWithReceiverAmbigousImport/ │ │ │ │ ├── dependency1.kt │ │ │ │ ├── dependency2.kt │ │ │ │ ├── other.kt │ │ │ │ ├── test.kt │ │ │ │ └── test.kt.after │ │ │ ├── extensionMethodInLambdaWithReceiverImport/ │ │ │ │ ├── dependency.kt │ │ │ │ ├── test.kt │ │ │ │ └── test.kt.after │ │ │ ├── extensionOperatorImport/ │ │ │ │ ├── dependency.kt │ │ │ │ ├── other1.kt │ │ │ │ ├── other2.kt │ │ │ │ ├── test.kt │ │ │ │ └── test.kt.after │ │ │ ├── extensionValImport/ │ │ │ │ ├── dependency.kt │ │ │ │ ├── other.kt │ │ │ │ ├── test.kt │ │ │ │ └── test.kt.after │ │ │ ├── extensionValReferenceImport/ │ │ │ │ ├── dependency.kt │ │ │ │ ├── other.kt │ │ │ │ ├── test.kt │ │ │ │ └── test.kt.after │ │ │ ├── functionExtensionValImport/ │ │ │ │ ├── dependency.kt │ │ │ │ ├── other.kt │ │ │ │ ├── test.kt │ │ │ │ └── test.kt.after │ │ │ ├── functionReferenceImport/ │ │ │ │ ├── dependency.kt │ │ │ │ ├── test.kt │ │ │ │ └── test.kt.after │ │ │ ├── importClassWithExistingPackageKeyword.kt │ │ │ ├── importClassWithExistingPackageKeyword.kt.after │ │ │ ├── importOnlyUnresolvedReferenceExpressions.kt │ │ │ ├── importOnlyUnresolvedReferenceExpressions.kt.after │ │ │ ├── importWithExtraBreakline.kt │ │ │ ├── importWithExtraBreakline.kt.after │ │ │ ├── importWithExtraBreaklineWithoutPackage.kt │ │ │ ├── importWithExtraBreaklineWithoutPackage.kt.after │ │ │ ├── invokableExtensionValImport/ │ │ │ │ ├── dependency.kt │ │ │ │ ├── other.kt │ │ │ │ ├── test.kt │ │ │ │ └── test.kt.after │ │ │ ├── localJavaClassAutoImport/ │ │ │ │ ├── Bar.kt │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java │ │ │ ├── localJavaEnumAutoImport/ │ │ │ │ ├── Bar.kt │ │ │ │ ├── Bar.kt.after │ │ │ │ └── FooEnum.java │ │ │ ├── localJavaInterfaceAutoImport/ │ │ │ │ ├── Bar.kt │ │ │ │ ├── Bar.kt.after │ │ │ │ └── FooInterface.java │ │ │ ├── oneStandardVectorAutoImport.kt │ │ │ ├── oneStandardVectorAutoImport.kt.after │ │ │ ├── packageArrayListAutoImport.kt │ │ │ ├── packageArrayListAutoImport.kt.after │ │ │ ├── packageLevelFunctionImport/ │ │ │ │ ├── dependency.kt │ │ │ │ ├── test.kt │ │ │ │ └── test.kt.after │ │ │ ├── packageLevelFunctionValImport/ │ │ │ │ ├── dependency.kt │ │ │ │ ├── test.kt │ │ │ │ └── test.kt.after │ │ │ ├── packageLevelInvokableValImport/ │ │ │ │ ├── dependency.kt │ │ │ │ ├── test.kt │ │ │ │ └── test.kt.after │ │ │ ├── packageLevelValImport/ │ │ │ │ ├── dependency.kt │ │ │ │ ├── test.kt │ │ │ │ └── test.kt.after │ │ │ ├── propertyReferenceImport/ │ │ │ │ ├── dependency.kt │ │ │ │ ├── test.kt │ │ │ │ └── test.kt.after │ │ │ ├── sameProjectJavaClassAutoImport/ │ │ │ │ ├── Bar.kt │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java │ │ │ ├── standardEnumMapAutoImport.kt │ │ │ ├── standardEnumMapAutoImport.kt.after │ │ │ └── unaryExtensionOperatorImport/ │ │ │ ├── dependency.kt │ │ │ ├── other1.kt │ │ │ ├── other2.kt │ │ │ ├── other3.kt │ │ │ ├── test.kt │ │ │ └── test.kt.after │ │ ├── basic/ │ │ │ ├── common/ │ │ │ │ ├── AfterFloatOnNewLine.kt │ │ │ │ ├── AfterIntSeparatedWithComments.kt │ │ │ │ ├── AutoCastAfterIf.kt │ │ │ │ ├── AutoCastAfterIfMethod.kt │ │ │ │ ├── AutoCastForThis.kt │ │ │ │ ├── AutoCastInWhen.kt │ │ │ │ ├── BasicAny.kt │ │ │ │ ├── BasicInt.kt │ │ │ │ ├── BeforeDotInCall.kt │ │ │ │ ├── CallLocalLambda.kt │ │ │ │ ├── ClassObjectElementsInClass.kt │ │ │ │ ├── ClassRedeclaration1.kt │ │ │ │ ├── ClassRedeclaration2.kt │ │ │ │ ├── ExtendClassName.kt │ │ │ │ ├── ExtendQualifiedClassName.kt │ │ │ │ ├── ExtensionForProperty.kt │ │ │ │ ├── ExtensionFunReceiver.kt │ │ │ │ ├── ExtensionFunReceiverForce.kt │ │ │ │ ├── ExtensionInsideFunction.kt │ │ │ │ ├── ExtensionToIntInFloatStyle.kt │ │ │ │ ├── FromImports.kt │ │ │ │ ├── FunctionCompletionFormatting.kt │ │ │ │ ├── InCallExpression.kt │ │ │ │ ├── InClassInitializer.kt │ │ │ │ ├── InClassPropertyAccessor.kt │ │ │ │ ├── InEmptyImport.kt │ │ │ │ ├── InExpressionNoPrefix.kt │ │ │ │ ├── InExtendTypeAnnotation.kt │ │ │ │ ├── InFileWithMultiDeclaration.kt │ │ │ │ ├── InFileWithTypedef.kt │ │ │ │ ├── InFunInClassInitializer.kt │ │ │ │ ├── InGlobalPropertyInitializer.kt │ │ │ │ ├── InImport.kt │ │ │ │ ├── InInitializerInPropertyAccessor.kt │ │ │ │ ├── InLocalObjectDeclaration.kt │ │ │ │ ├── InLongDotQualifiedExpression.kt │ │ │ │ ├── InMiddleOfPackage.kt │ │ │ │ ├── InMiddleOfPackageDirective.kt │ │ │ │ ├── InObjectInDelegationSpecifier.kt │ │ │ │ ├── InPackageBegin.kt │ │ │ │ ├── InParametersTypes.kt │ │ │ │ ├── InParametersTypesForce.kt │ │ │ │ ├── InTypeAnnotation.kt │ │ │ │ ├── JavaPackage.kt │ │ │ │ ├── LocalMultideclarationValues.kt │ │ │ │ ├── NamedObject.kt │ │ │ │ ├── NoClassNameDuplication.kt │ │ │ │ ├── NoCompletionAfterBigFloat.kt │ │ │ │ ├── NoCompletionAfterFloat.kt │ │ │ │ ├── NoCompletionAfterInt.kt │ │ │ │ ├── NoCompletionAfterLong.kt │ │ │ │ ├── NoEmptyPackage.kt │ │ │ │ ├── NoObjectInTypePosition.kt │ │ │ │ ├── NoTopLevelCompletionInQualifiedUserTypes.kt │ │ │ │ ├── ObjectRedeclaration1.kt │ │ │ │ ├── ObjectRedeclaration2.kt │ │ │ │ ├── OneProposalWithExplicitImport.kt │ │ │ │ ├── OneWithStarImport.kt │ │ │ │ ├── OnlyScopedClassesWithoutExplicit.kt │ │ │ │ ├── OverloadFunctions.kt │ │ │ │ ├── ShortClassNamesInTypePosition.kt │ │ │ │ ├── StandardJetArrayFirst.kt │ │ │ │ ├── StandardJetDoubleFirst.kt │ │ │ │ ├── SubpackageInFun.kt │ │ │ │ ├── TopLevelClassCompletionInQualifiedCall.kt │ │ │ │ ├── VariableClassName.kt │ │ │ │ ├── VariableWithLowerCase.kt │ │ │ │ ├── VisibilityClassMembersFromExternal.kt │ │ │ │ ├── WithCompletedExpression.kt │ │ │ │ ├── functionWithLowerCase.kt │ │ │ │ ├── notImportedAnnotation.kt │ │ │ │ └── visibility/ │ │ │ │ └── VisibilityPrivateToThisWithWrongThis.kt │ │ │ ├── java/ │ │ │ │ ├── AutoForceCompletion.kt │ │ │ │ ├── ExtensionFromStandardLibrary.kt │ │ │ │ ├── InPackage.kt │ │ │ │ ├── JavaClassNames.kt │ │ │ │ ├── JavaConstructorsCompletion.kt │ │ │ │ ├── NoClassNameDuplicationForRuntimeClass.kt │ │ │ │ ├── NoImportedJavaClassDuplication.kt │ │ │ │ ├── PropertyMetadata.kt │ │ │ │ ├── TopLevelFromStandardLibrary.kt │ │ │ │ └── TopLevelFromStandardLibraryWithoutParam.kt │ │ │ └── scripts/ │ │ │ ├── absentMainTemplate.kts │ │ │ ├── argsCompletion.kts │ │ │ ├── classFromJRE.kts │ │ │ ├── functionFromStdlib.kts │ │ │ ├── keywordsCompletion.kts │ │ │ ├── localDeclarations.kts │ │ │ └── typeFromRuntime.kts │ │ ├── handlers/ │ │ │ ├── ExistingSingleBrackets.kt │ │ │ ├── ExistingSingleBrackets.kt.after │ │ │ ├── FunctionWithParamOnBracket.kt │ │ │ ├── FunctionWithParamOnBracket.kt.after │ │ │ ├── completeNonImported.kt │ │ │ ├── completeNonImported.kt.after │ │ │ ├── completeWithExistingBraces.kt │ │ │ ├── completeWithExistingBraces.kt.after │ │ │ ├── completeWithExistingBracesOnBrace.kt │ │ │ ├── completeWithExistingBracesOnBrace.kt.after │ │ │ ├── completeWithExistingBracesOnDot.kt │ │ │ ├── completeWithExistingBracesOnDot.kt.after │ │ │ ├── filterTypesFromSamePackage.dependency.kt │ │ │ ├── filterTypesFromSamePackage.kt │ │ │ ├── filterTypesFromSamePackage.kt.after │ │ │ ├── functionLiteralInsertOnSpace.kt │ │ │ ├── functionLiteralInsertOnSpace.kt.after │ │ │ ├── functionWithParamOnDot.kt │ │ │ ├── functionWithParamOnDot.kt.after │ │ │ ├── higherOrderFunction.kt │ │ │ ├── higherOrderFunction.kt.after │ │ │ ├── higherOrderFunctionWithArgs1.kt │ │ │ ├── higherOrderFunctionWithArgs1.kt.after │ │ │ ├── insertFunctionWithBothParentheses.kt │ │ │ ├── insertFunctionWithBothParentheses.kt.after │ │ │ ├── insertFunctionWithSingleParameterWithBrace.kt │ │ │ ├── insertFunctionWithSingleParameterWithBrace.kt.after │ │ │ ├── insertJavaMethodWithParam.kt │ │ │ ├── insertJavaMethodWithParam.kt.after │ │ │ ├── insertVoidJavaMethod.kt │ │ │ ├── insertVoidJavaMethod.kt.after │ │ │ ├── noParamsFunction.kt │ │ │ ├── noParamsFunction.kt.after │ │ │ ├── nonImportedByCamelCase.kt │ │ │ ├── nonImportedByCamelCase.kt.after │ │ │ ├── paramFunctionOnBracket.kt │ │ │ ├── paramFunctionOnBracket.kt.after │ │ │ ├── paramFunctionOnDot.kt │ │ │ ├── paramFunctionOnDot.kt.after │ │ │ ├── paramsFunction.kt │ │ │ ├── paramsFunction.kt.after │ │ │ ├── paramsFunctionOnDot.kt │ │ │ ├── paramsFunctionOnDot.kt.after │ │ │ ├── singleBrackets.kt │ │ │ ├── singleBrackets.kt.after │ │ │ ├── unitFunctionOnBracket.kt │ │ │ ├── unitFunctionOnBracket.kt.after │ │ │ ├── unitFunctionOnDot.kt │ │ │ ├── unitFunctionOnDot.kt.after │ │ │ ├── withLambdaAndBraces.kt │ │ │ ├── withLambdaAndBraces.kt.after │ │ │ ├── withLambdaAndBracesOnDot.kt │ │ │ ├── withLambdaAndBracesOnDot.kt.after │ │ │ ├── withParamsAndBraces.kt │ │ │ ├── withParamsAndBraces.kt.after │ │ │ ├── withParamsAndBracesOnBrace.kt │ │ │ ├── withParamsAndBracesOnBrace.kt.after │ │ │ ├── withParamsAndBracesOnDot.kt │ │ │ └── withParamsAndBracesOnDot.kt.after │ │ ├── keywords/ │ │ │ └── InFunctionTypePosition.kt │ │ └── relevance/ │ │ ├── byCamelCaseLocal.kt │ │ ├── byPrefixMatchLocal.kt │ │ ├── byPrefixWithImported.kt │ │ ├── localBeforeNonImported.kt │ │ ├── sortingForLocal.kt │ │ └── sortingForNonImported.kt │ ├── diagnostics/ │ │ ├── FunctionCalleeExpressions.kt │ │ ├── FunctionCalleeExpressions.txt │ │ ├── annotationAsJavaAnnotationArgument.kt │ │ ├── constAsJavaAnnotationArgument.kt │ │ └── resolveConstructor.kt │ ├── findUsages/ │ │ ├── java/ │ │ │ ├── JKClassAllUsages.0.java │ │ │ ├── JKClassAllUsages.1.kt │ │ │ ├── JKClassAllUsages.results.txt │ │ │ ├── JKClassDerivedAnonymousObjects.0.java │ │ │ ├── JKClassDerivedAnonymousObjects.1.kt │ │ │ ├── JKClassDerivedAnonymousObjects.results.txt │ │ │ ├── JKClassDerivedClasses.0.java │ │ │ ├── JKClassDerivedClasses.1.kt │ │ │ ├── JKClassDerivedClasses.results.txt │ │ │ ├── JKClassDerivedInnerClasses.0.java │ │ │ ├── JKClassDerivedInnerClasses.1.kt │ │ │ ├── JKClassDerivedInnerClasses.results.txt │ │ │ ├── JKClassDerivedInnerObjects.0.java │ │ │ ├── JKClassDerivedInnerObjects.1.kt │ │ │ ├── JKClassDerivedInnerObjects.results.txt │ │ │ ├── JKClassDerivedLocalClasses.0.java │ │ │ ├── JKClassDerivedLocalClasses.1.kt │ │ │ ├── JKClassDerivedLocalClasses.results.txt │ │ │ ├── JKClassDerivedLocalObjects.0.java │ │ │ ├── JKClassDerivedLocalObjects.1.kt │ │ │ ├── JKClassDerivedLocalObjects.results.txt │ │ │ ├── JKClassDerivedObjects.0.java │ │ │ ├── JKClassDerivedObjects.1.kt │ │ │ ├── JKClassDerivedObjects.results.txt │ │ │ ├── JKClassWithImplicitConstructorAllUsages.0.java │ │ │ ├── JKClassWithImplicitConstructorAllUsages.1.kt │ │ │ ├── JKClassWithImplicitConstructorAllUsages.results.txt │ │ │ ├── JKDerivedInterfaces.0.java │ │ │ ├── JKDerivedInterfaces.1.kt │ │ │ ├── JKDerivedInterfaces.results.txt │ │ │ ├── JKNestedClassAllUsages.0.java │ │ │ ├── JKNestedClassAllUsages.1.kt │ │ │ └── JKNestedClassAllUsages.results.txt │ │ └── kotlin/ │ │ ├── findFunctionUsages/ │ │ │ ├── javaMethodUsages.0.kt │ │ │ ├── javaMethodUsages.1.java │ │ │ ├── javaMethodUsages.results.txt │ │ │ ├── kotlinMethodUsages.0.kt │ │ │ ├── kotlinMethodUsages.1.kt │ │ │ ├── kotlinMethodUsages.results.txt │ │ │ ├── kotlinMultiRefInImport.0.kt │ │ │ ├── kotlinMultiRefInImport.1.kt │ │ │ └── kotlinMultiRefInImport.results.txt │ │ ├── findObjectUsages/ │ │ │ ├── javaObjectUsages.0.kt │ │ │ ├── javaObjectUsages.1.java │ │ │ ├── javaObjectUsages.results.txt │ │ │ ├── kotlinNestedObjectUsages.0.kt │ │ │ ├── kotlinNestedObjectUsages.1.kt │ │ │ ├── kotlinNestedObjectUsages.results.txt │ │ │ ├── kotlinObjectUsages.0.kt │ │ │ ├── kotlinObjectUsages.1.kt │ │ │ └── kotlinObjectUsages.results.txt │ │ ├── findPrimaryConstructorUsages/ │ │ │ ├── primaryConstructorByRef.0.kt │ │ │ ├── primaryConstructorByRef.results.txt │ │ │ ├── primaryConstructorWithKeyword.0.kt │ │ │ └── primaryConstructorWithKeyword.results.txt │ │ └── findPropertyUsages/ │ │ ├── kotlinTopLevelPropertyUsages.0.kt │ │ ├── kotlinTopLevelPropertyUsages.1.kt │ │ ├── kotlinTopLevelPropertyUsages.2.java │ │ └── kotlinTopLevelPropertyUsages.results.txt │ ├── format/ │ │ ├── autoIndent/ │ │ │ ├── afterFunCallInScript.after.kts │ │ │ ├── afterFunCallInScript.kts │ │ │ ├── afterOneOpenBrace.after.kt │ │ │ ├── afterOneOpenBrace.kt │ │ │ ├── afterOpenBraceWithShift.after.kt │ │ │ ├── afterOpenBraceWithShift.kt │ │ │ ├── afterOperatorIfWithoutBraces.after.kt │ │ │ ├── afterOperatorIfWithoutBraces.kt │ │ │ ├── afterOperatorWhileWithoutBraces.after.kt │ │ │ ├── afterOperatorWhileWithoutBraces.kt │ │ │ ├── beforeCloseBrace.after.kt │ │ │ ├── beforeCloseBrace.kt │ │ │ ├── beforeFunctionStart.after.kt │ │ │ ├── beforeFunctionStart.kt │ │ │ ├── betweenBracesOnDifferentLine.after.kt │ │ │ ├── betweenBracesOnDifferentLine.kt │ │ │ ├── betweenBracesOnOneLine.after.kt │ │ │ ├── betweenBracesOnOneLine.kt │ │ │ ├── betweenBracesWithSpacesAtStart.after.kt │ │ │ ├── betweenBracesWithSpacesAtStart.kt │ │ │ ├── betweenBracesWithSpacesEnd1.after.kt │ │ │ ├── betweenBracesWithSpacesEnd1.kt │ │ │ ├── betweenBracesWithSpacesEnd2.after.kt │ │ │ ├── betweenBracesWithSpacesEnd2.kt │ │ │ ├── betweenBracesWithSpacesMiddle.after.kt │ │ │ ├── betweenBracesWithSpacesMiddle.kt │ │ │ ├── breakLineAfterIfWithoutBraces.after.kt │ │ │ ├── breakLineAfterIfWithoutBraces.kt │ │ │ ├── continuationAfterDotCall.after.kt │ │ │ ├── continuationAfterDotCall.kt │ │ │ ├── continuationBeforeFunName.after.kt │ │ │ ├── continuationBeforeFunName.kt │ │ │ ├── indentBeforeWhile.after.kt │ │ │ ├── indentBeforeWhile.kt │ │ │ ├── lineBreakSaveIndent.after.kt │ │ │ ├── lineBreakSaveIndent.kt │ │ │ ├── nestedOperatorsWithBraces.after.kt │ │ │ ├── nestedOperatorsWithBraces.kt │ │ │ ├── nestedOperatorsWithoutBraces.after.kt │ │ │ ├── nestedOperatorsWithoutBraces.kt │ │ │ ├── newLineInParameters1.after.kt │ │ │ ├── newLineInParameters1.kt │ │ │ ├── newLineInParameters2.after.kt │ │ │ ├── newLineInParameters2.kt │ │ │ ├── sampleTest.after.kt │ │ │ └── sampleTest.kt │ │ ├── blockCommentBeforeDeclaration.kt │ │ ├── blockCommentBeforeDeclaration.kt.after │ │ ├── classesAndPropertiesFormatTest.kt │ │ ├── classesAndPropertiesFormatTest.kt.after │ │ ├── commentOnTheLastLineOfLambda.kt │ │ ├── commentOnTheLastLineOfLambda.kt.after │ │ ├── formatScriptFile.kts │ │ ├── formatScriptFile.kts.after │ │ ├── formatSelection.kt │ │ ├── formatSelection.kt.after │ │ ├── indentInDoWhile.kt │ │ ├── indentInDoWhile.kt.after │ │ ├── indentInIfExpressionBlock.kt │ │ ├── indentInIfExpressionBlock.kt.after │ │ ├── indentInPropertyAccessor.kt │ │ ├── indentInPropertyAccessor.kt.after │ │ ├── indentInWhenEntry.kt │ │ ├── indentInWhenEntry.kt.after │ │ ├── initIndent.kt │ │ ├── initIndent.kt.after │ │ ├── lambdaInBlock.kt │ │ ├── lambdaInBlock.kt.after │ │ ├── newLineAfterImportsAndPackage.kt │ │ ├── newLineAfterImportsAndPackage.kt.after │ │ ├── objectsAndLocalFunctionsFormatTest.kt │ │ ├── objectsAndLocalFunctionsFormatTest.kt.after │ │ ├── packageFunctionsFormatTest.kt │ │ ├── packageFunctionsFormatTest.kt.after │ │ ├── respectCaretAfterFormatting.kt │ │ ├── respectCaretAfterFormatting.kt.after │ │ ├── withBlockComments.kt │ │ ├── withBlockComments.kt.after │ │ ├── withJavaDoc.kt │ │ ├── withJavaDoc.kt.after │ │ ├── withLineComments.kt │ │ ├── withLineComments.kt.after │ │ ├── withMutableVariable.kt │ │ ├── withMutableVariable.kt.after │ │ ├── withWhitespaceBeforeBrace.kt │ │ ├── withWhitespaceBeforeBrace.kt.after │ │ ├── withoutComments.kt │ │ └── withoutComments.kt.after │ ├── highlighting/ │ │ ├── basic/ │ │ │ ├── blockComment.kt │ │ │ ├── forKeyword.kt │ │ │ ├── function.kt │ │ │ ├── getterSetter.kt │ │ │ ├── highlightCompanionObject.kt │ │ │ ├── importKeyword.kt │ │ │ ├── inKeyword.kt │ │ │ ├── interfaceKeyword.kt │ │ │ ├── kdocBasic.kt │ │ │ ├── kdocWithEmptyLines.kt │ │ │ ├── kdocWithMyTag.kt │ │ │ ├── kdocWithParam.kt │ │ │ ├── kdocWithProperty.kt │ │ │ ├── kdocWithSee.kt │ │ │ ├── kdocWithThrows.kt │ │ │ ├── kdocWithoutLeadingAsterisk.kt │ │ │ ├── keywordWithText.kt │ │ │ ├── openKeyword.kt │ │ │ ├── singleLineComment.kt │ │ │ ├── softImportKeyword.kt │ │ │ ├── softKeywords.kt │ │ │ ├── stringInterpolation.kt │ │ │ ├── stringToken.kt │ │ │ ├── textWithTokenBetween.kt │ │ │ ├── textWithTokenInPrefix.kt │ │ │ └── textWithTokenInSuffix.kt │ │ └── positionUpdater/ │ │ ├── afterFunctionName.kt │ │ ├── afterFunctionName.kt.after │ │ ├── afterHighlightedPosition.kt │ │ ├── afterHighlightedPosition.kt.after │ │ ├── beforeFunctionName.kt │ │ ├── beforeFunctionName.kt.after │ │ ├── beforeHighlightedPosition.kt │ │ ├── beforeHighlightedPosition.kt.after │ │ ├── illegalCharactersAfter.kt │ │ ├── illegalCharactersAfter.kt.after │ │ ├── illegalCharactersBefore.kt │ │ ├── illegalCharactersBefore.kt.after │ │ ├── illegalCharactersBeforeHighlightedPosition.kt │ │ ├── illegalCharactersBeforeHighlightedPosition.kt.after │ │ ├── insideHighlightedPosition.kt │ │ └── insideHighlightedPosition.kt.after │ ├── ide_analyzer/ │ │ ├── analyzerHasKotlinAnnotations.kt │ │ ├── analyzerHasKotlinRuntime.kt │ │ ├── checkAnalyzerFoundError.kt │ │ ├── checkExistancePackageLevelFunctions/ │ │ │ ├── Bar.kt │ │ │ ├── Baz.kt │ │ │ └── Foo.java │ │ ├── checkTestsFoundJavaError/ │ │ │ └── J1.java │ │ ├── companionObjectFromJava/ │ │ │ ├── Bar.kt │ │ │ └── Foo.java │ │ ├── javaFromKotlin/ │ │ │ ├── Bar.kt │ │ │ └── Foo.java │ │ ├── kotlinFromJava/ │ │ │ ├── Bar.kt │ │ │ └── Foo.java │ │ ├── kotlinInPackageFromJava/ │ │ │ ├── J1.java │ │ │ └── K1.kt │ │ ├── kotlinJavaKotlin/ │ │ │ ├── J1.java │ │ │ ├── K1.kt │ │ │ └── K2.kt │ │ ├── kotlinWithErrorsFromJava/ │ │ │ ├── J1.java │ │ │ └── K1.kt │ │ ├── packageLevelFunctionsFromJava/ │ │ │ ├── Bar.kt │ │ │ └── Foo.java │ │ ├── packageLevelPropertiesFromJava/ │ │ │ ├── Bar.kt │ │ │ └── Foo.java │ │ └── unresolvedPackageType/ │ │ ├── Bar.kt │ │ └── Baz.kt │ ├── intentions/ │ │ ├── changeReturnType/ │ │ │ ├── changeReturnTypeInScript.kts │ │ │ ├── changeReturnTypeInScript.kts.after │ │ │ ├── typeMismatchInReturnLambda.kt │ │ │ ├── typeMismatchInReturnLambda.kt.after │ │ │ ├── typeMismatchInReturnLambdaWithLabel.kt │ │ │ └── typeMismatchInReturnLambdaWithLabel.kt.after │ │ ├── convertToBlockBody/ │ │ │ ├── implicitlyNonUnitFun.kt │ │ │ └── implicitlyNonUnitFun.kt.after │ │ ├── convertToExpressionBody/ │ │ │ ├── anonymousObjectExpression.kt │ │ │ ├── anonymousObjectExpression.kt.after │ │ │ ├── funWithImplicitUnitTypeWithThrow.kt │ │ │ ├── funWithImplicitUnitTypeWithThrow.kt.after │ │ │ ├── funWithNothingType.kt │ │ │ ├── funWithNothingType.kt.after │ │ │ ├── funWithReturn.kt │ │ │ ├── funWithReturn.kt.after │ │ │ ├── funWithUnitTypeWithThrow.kt │ │ │ └── funWithUnitTypeWithThrow.kt.after │ │ ├── implementMethods/ │ │ │ ├── implementMethodInScript.kts │ │ │ └── implementMethodInScript.kts.after │ │ ├── replaceGetOrSet/ │ │ │ ├── replaceGetInScript.kts │ │ │ └── replaceGetInScript.kts.after │ │ └── specifyType/ │ │ ├── ClassNameClashing.kt │ │ ├── ClassNameClashing.kt.after │ │ ├── StringRedefined.kt │ │ └── StringRedefined.kt.after │ ├── launch/ │ │ └── junit/ │ │ ├── RunTestExtendingTestCase.kt │ │ └── SimpleJUnitTests.kt │ ├── markers/ │ │ └── parsing/ │ │ ├── classDefinitionTypoErrorTest.kt │ │ ├── classDefinitionTypoErrorTest.kt.after │ │ ├── excessBraceTypingErrorTest.kt │ │ ├── excessBraceTypingErrorTest.kt.after │ │ ├── missingClosingBraceErrorTest.kt │ │ ├── missingClosingBraceErrorTest.kt.after │ │ ├── missingFunctionBodyErrorTest.kt │ │ └── missingFunctionBodyErrorTest.kt.after │ ├── navigation/ │ │ ├── fromGetterSyntheticProperty/ │ │ │ ├── Bar.kt.before │ │ │ └── Foo.java.after │ │ ├── fromSetterSyntheticProperty/ │ │ │ ├── Bar.kt.before │ │ │ └── Foo.java.after │ │ ├── fromSyntheticPropertyOnlyWithGetter/ │ │ │ ├── Bar.kt.before │ │ │ └── Foo.java.after │ │ ├── javaToKotlin/ │ │ │ ├── specifiedPackageLevelFunction/ │ │ │ │ ├── Bar.kt │ │ │ │ ├── Baz.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toBasicProperty/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toBasicTopLevelProperty/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toCompanionObject/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toFilePart/ │ │ │ │ ├── Baz.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toFunInBaseClass/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toFunctionInEnumClass/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toFunctionInFilePart/ │ │ │ │ ├── Baz.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toFunctionInInnerClass/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toFunctionInObject/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toFunctionWithExistingConstructorEqualSignature/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toFunctionWithExistingEqualSignature/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toFunctionWithNameDuplicate/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toFunctionWithNameDuplicateInClass/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toFunctionWithPlatformName/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toInnerKotlinClass/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toInnerKotlinEnumClass/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toInnerKotlinEnumEntry/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toKotlinClass/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toKotlinClassInPackage/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toKotlinEnumClass/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toKotlinEnumEntry/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toKotlinFunction/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toKotlinFunctionInCompanion/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toKotlinObject/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toKotlinSuperClass/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toKotlinTopLevelFunction/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toMethodWithDefaultArg/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toMutablePropertyFromGetter/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toMutablePropertyFromSetter/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toMutablePropertyInCompanion/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toNamedCompanionObject/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toNestedCompanionObject/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toObjectInstance/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toOverloadMethod1/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toOverloadMethod2/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toOverridenProperty/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toParametrizedClass/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toParametrizedFunction/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toParametrizedFunctionWithOverload/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toPrimaryConstructor/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toPropertyInBaseClass/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toPropertyInCompanion/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toPropertyWithGetter/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toPropertyWithSetter/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toSecondaryConstructor1/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toSecondaryConstructor2/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ ├── toTopLevelPropertyWithGetter/ │ │ │ │ ├── Bar.kt.after │ │ │ │ └── Foo.java.before │ │ │ └── toTopLevelPropertyWithSetter/ │ │ │ ├── Bar.kt.after │ │ │ └── Foo.java.before │ │ ├── scripts/ │ │ │ └── basic/ │ │ │ ├── toFunction.kts │ │ │ ├── toFunction.kts.after │ │ │ ├── toVariable.kts │ │ │ └── toVariable.kts.after │ │ ├── toJavaClassNavigation/ │ │ │ ├── Bar.kt.before │ │ │ └── Foo.java.after │ │ ├── toJavaGetterMethod/ │ │ │ ├── Bar.kt.before │ │ │ └── Foo.java.after │ │ ├── toJavaMethodNavigation/ │ │ │ ├── Bar.kt.before │ │ │ └── Foo.java.after │ │ ├── toKotlinClassNavigation/ │ │ │ ├── Bar.kt │ │ │ ├── Baz.kt.before │ │ │ └── Foo.kt.after │ │ ├── toKotlinMethodNavigation/ │ │ │ ├── Bar.kt │ │ │ ├── Baz.kt.before │ │ │ └── Foo.kt.after │ │ ├── withinFileFromConstructorToClassNavigation.kt │ │ ├── withinFileFromConstructorToClassNavigation.kt.after │ │ ├── withinFileToClassNavigation.kt │ │ ├── withinFileToClassNavigation.kt.after │ │ ├── withinFileToMethodNavigation.kt │ │ └── withinFileToMethodNavigation.kt.after │ ├── organizeImports/ │ │ ├── doNotInsertLinesForNoErrors.kt │ │ ├── doNotInsertLinesForNoErrors.kt.after │ │ ├── importOneClass.kt │ │ ├── importOneClass.kt.after │ │ ├── importSeveralClasses.kt │ │ ├── importSeveralClasses.kt.after │ │ ├── importSeveralClassesWithExistingPackage.kt │ │ ├── importSeveralClassesWithExistingPackage.kt.after │ │ └── includeImportsOnlyFromActiveFile/ │ │ ├── Bar.kt │ │ ├── Bar.kt.after │ │ └── Baz.kt │ ├── refactoring/ │ │ └── rename/ │ │ ├── automaticRenamer/ │ │ │ ├── after/ │ │ │ │ ├── JavaFoo.java │ │ │ │ ├── lib.kt │ │ │ │ └── main.kt │ │ │ ├── before/ │ │ │ │ ├── JavaFoo.java │ │ │ │ ├── lib.kt │ │ │ │ └── main.kt │ │ │ └── simple.test │ │ ├── renameJavaClass/ │ │ │ ├── after/ │ │ │ │ ├── RenameJavaClass.kt │ │ │ │ └── testing/ │ │ │ │ └── NewName.java │ │ │ ├── before/ │ │ │ │ ├── RenameJavaClass.kt │ │ │ │ └── testing/ │ │ │ │ └── SomeClass.java │ │ │ └── renameJavaClass.test │ │ ├── renameJavaClassSamePackage/ │ │ │ ├── after/ │ │ │ │ ├── RenameJavaClassSamePackage.kt │ │ │ │ └── testing/ │ │ │ │ └── NewName.java │ │ │ ├── before/ │ │ │ │ ├── RenameJavaClassSamePackage.kt │ │ │ │ └── testing/ │ │ │ │ └── SomeClass.java │ │ │ └── renameJavaClassSamePackage.test │ │ ├── renameJavaInterface/ │ │ │ ├── after/ │ │ │ │ ├── RenameJavaClass.kt │ │ │ │ └── testing/ │ │ │ │ └── NewInterface.java │ │ │ ├── before/ │ │ │ │ ├── RenameJavaClass.kt │ │ │ │ └── testing/ │ │ │ │ └── SomeInterface.java │ │ │ └── renameJavaInterface.test │ │ ├── renameJavaMethod/ │ │ │ ├── after/ │ │ │ │ ├── MethodUsages.kt │ │ │ │ └── testing/ │ │ │ │ └── JavaClass.java │ │ │ ├── before/ │ │ │ │ ├── MethodUsages.kt │ │ │ │ └── testing/ │ │ │ │ └── JavaClass.java │ │ │ ├── javaBaseMethod.test │ │ │ └── kotlinOverridenMethod.test │ │ ├── renameJavaStaticMethod/ │ │ │ ├── after/ │ │ │ │ ├── Some.kt │ │ │ │ └── SomeJava.java │ │ │ ├── before/ │ │ │ │ ├── Some.kt │ │ │ │ └── SomeJava.java │ │ │ └── renameJavaStaticMethod.test │ │ ├── renameKotlinBaseMethod/ │ │ │ ├── after/ │ │ │ │ ├── RenameKotlinBaseMethod.kt │ │ │ │ └── testing/ │ │ │ │ └── JavaClient.java │ │ │ ├── before/ │ │ │ │ ├── RenameKotlinBaseMethod.kt │ │ │ │ └── testing/ │ │ │ │ └── JavaClient.java │ │ │ ├── javaWrapperForBaseFunction.test │ │ │ ├── javaWrapperForOverridenFunctionWithKotlinBase.test │ │ │ └── kotlinBaseFunction.test │ │ ├── renameKotlinClass/ │ │ │ ├── after/ │ │ │ │ ├── RenameKotlinClass.kt │ │ │ │ ├── Second.kt │ │ │ │ └── testing/ │ │ │ │ └── JavaClient.java │ │ │ ├── before/ │ │ │ │ ├── RenameKotlinClass.kt │ │ │ │ ├── Second.kt │ │ │ │ └── testing/ │ │ │ │ └── JavaClient.java │ │ │ ├── javaWrapperForKotlinClass.test │ │ │ └── kotlinClass.test │ │ ├── renameKotlinClassByConstructorRef/ │ │ │ ├── after/ │ │ │ │ └── main.kt │ │ │ ├── before/ │ │ │ │ └── main.kt │ │ │ └── renameKotlinClassByConstructorRef.test │ │ ├── renameKotlinClassFromJava/ │ │ │ ├── after/ │ │ │ │ ├── JavaUsage.java │ │ │ │ └── KotlinCls.kt │ │ │ ├── before/ │ │ │ │ ├── JavaUsage.java │ │ │ │ └── KotlinCls.kt │ │ │ └── renameKotlinClassFromJava.test │ │ ├── renameKotlinMethod/ │ │ │ ├── after/ │ │ │ │ ├── RenameKotlinMethod.kt │ │ │ │ └── testing/ │ │ │ │ └── JavaClient.java │ │ │ ├── before/ │ │ │ │ ├── RenameKotlinMethod.kt │ │ │ │ └── testing/ │ │ │ │ └── JavaClient.java │ │ │ ├── javaWrapperForKotlinMethod.test │ │ │ └── renameKotlinMethod.test │ │ ├── renameKotlinMethodFromJava/ │ │ │ ├── after/ │ │ │ │ ├── JavaUsage.java │ │ │ │ └── KotlinCls.kt │ │ │ ├── before/ │ │ │ │ ├── JavaUsage.java │ │ │ │ └── KotlinCls.kt │ │ │ └── renameKotlinMethodFromJava.test │ │ ├── renameKotlinTopLevelFun/ │ │ │ ├── after/ │ │ │ │ ├── Some.kt │ │ │ │ └── SomeJava.java │ │ │ ├── before/ │ │ │ │ ├── Some.kt │ │ │ │ └── SomeJava.java │ │ │ └── renameKotlinTopLevelFun.test │ │ ├── renameKotlinTopLevelFunFromJava/ │ │ │ ├── after/ │ │ │ │ ├── JavaUsage.java │ │ │ │ └── KotlinCls.kt │ │ │ ├── before/ │ │ │ │ ├── JavaUsage.java │ │ │ │ └── KotlinCls.kt │ │ │ └── renameKotlinTopLevelFunFromJava.test │ │ ├── scripts/ │ │ │ ├── renameClassInScript/ │ │ │ │ ├── after/ │ │ │ │ │ └── main.kts │ │ │ │ ├── before/ │ │ │ │ │ └── main.kts │ │ │ │ └── info.test │ │ │ ├── renameFunctionInScript/ │ │ │ │ ├── after/ │ │ │ │ │ └── main.kts │ │ │ │ ├── before/ │ │ │ │ │ └── main.kts │ │ │ │ └── info.test │ │ │ ├── renameInScriptLocally/ │ │ │ │ ├── after/ │ │ │ │ │ ├── main.kts │ │ │ │ │ └── other.kts │ │ │ │ ├── before/ │ │ │ │ │ ├── main.kts │ │ │ │ │ └── other.kts │ │ │ │ └── info.test │ │ │ └── renamePropertyInScript/ │ │ │ ├── after/ │ │ │ │ └── main.kts │ │ │ ├── before/ │ │ │ │ └── main.kts │ │ │ └── info.test │ │ └── simple/ │ │ ├── after/ │ │ │ └── main.kt │ │ ├── before/ │ │ │ └── main.kt │ │ └── info.test │ ├── scripts/ │ │ └── templates/ │ │ ├── customEPResolver.kts │ │ ├── sample.testDef.kts │ │ ├── sampleEx.testDef.kts │ │ └── standard.kts │ └── wordSelection/ │ ├── selectEnclosing/ │ │ ├── DocComment/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ ├── 2.kt │ │ │ └── 3.kt │ │ ├── ForRange/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ ├── 2.kt │ │ │ └── 3.kt │ │ ├── FunctionWithLineCommentAfter/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ ├── 2.kt │ │ │ └── 3.kt │ │ ├── FunctionWithLineCommentBefore/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ ├── 2.kt │ │ │ └── 3.kt │ │ ├── IfBody/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ ├── 2.kt │ │ │ ├── 3.kt │ │ │ ├── 4.kt │ │ │ └── 5.kt │ │ ├── IfCondition/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ ├── 2.kt │ │ │ └── 3.kt │ │ ├── LineComment/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ └── 2.kt │ │ ├── ShiftOnWhitespace/ │ │ │ ├── 0.kt │ │ │ └── 1.kt │ │ ├── SimpleComment/ │ │ │ ├── 0.kt │ │ │ └── 1.kt │ │ ├── SimpleStringLiteral/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ └── 2.kt │ │ ├── SimpleStringLiteral2/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ └── 2.kt │ │ ├── Statements/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ ├── 2.kt │ │ │ ├── 3.kt │ │ │ ├── 4.kt │ │ │ ├── 5.kt │ │ │ ├── 6.kt │ │ │ ├── 7.kt │ │ │ ├── 8.kt │ │ │ └── 9.kt │ │ ├── StatementsWithWindowsDelimiter/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ ├── 2.kt │ │ │ ├── 3.kt │ │ │ ├── 4.kt │ │ │ ├── 5.kt │ │ │ ├── 6.kt │ │ │ ├── 7.kt │ │ │ ├── 8.kt │ │ │ └── 9.kt │ │ ├── TemplateStringLiteral1/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ ├── 2.kt │ │ │ └── 3.kt │ │ ├── TemplateStringLiteral2/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ ├── 2.kt │ │ │ ├── 3.kt │ │ │ └── 4.kt │ │ ├── TemplateStringLiteral3/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ ├── 2.kt │ │ │ ├── 3.kt │ │ │ ├── 4.kt │ │ │ └── 5.kt │ │ ├── TypeArguments/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ └── 2.kt │ │ ├── TypeParameters/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ └── 2.kt │ │ ├── ValueArguments/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ └── 2.kt │ │ ├── ValueParameters/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ └── 2.kt │ │ ├── WhenEntries/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ ├── 2.kt │ │ │ ├── 3.kt │ │ │ └── 4.kt │ │ ├── WholeFileSelection/ │ │ │ ├── 0.kt │ │ │ └── 1.kt │ │ └── selectEnclosingFunctionNameWithoutSelection/ │ │ ├── 0.kt │ │ ├── 1.kt │ │ ├── 2.kt │ │ ├── 3.kt │ │ ├── 4.kt │ │ ├── 5.kt │ │ └── 6.kt │ ├── selectNext/ │ │ ├── BlockStatements/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ ├── 2.kt │ │ │ ├── 3.kt │ │ │ ├── 4.kt │ │ │ ├── 5.kt │ │ │ ├── 6.kt │ │ │ ├── 7.kt │ │ │ ├── 8.kt │ │ │ └── 9.kt │ │ ├── BlockStatementsWithWindowsDelimiter/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ ├── 2.kt │ │ │ ├── 3.kt │ │ │ ├── 4.kt │ │ │ ├── 5.kt │ │ │ ├── 6.kt │ │ │ ├── 7.kt │ │ │ ├── 8.kt │ │ │ └── 9.kt │ │ ├── Classes/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ ├── 2.kt │ │ │ ├── 3.kt │ │ │ └── 4.kt │ │ ├── DocComment/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ ├── 2.kt │ │ │ ├── 3.kt │ │ │ └── 4.kt │ │ ├── FunctionWithLineComments/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ ├── 2.kt │ │ │ ├── 3.kt │ │ │ └── 4.kt │ │ ├── Functions/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ └── 2.kt │ │ ├── Imports/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ ├── 2.kt │ │ │ ├── 3.kt │ │ │ ├── 4.kt │ │ │ ├── 5.kt │ │ │ ├── 6.kt │ │ │ └── 7.kt │ │ ├── NonTraversableElement/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ └── 2.kt │ │ ├── ShiftOnWhitespace/ │ │ │ ├── 0.kt │ │ │ └── 1.kt │ │ ├── TemplateStringLiteral/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ ├── 2.kt │ │ │ ├── 3.kt │ │ │ ├── 4.kt │ │ │ └── 5.kt │ │ ├── TypeArguments/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ └── 2.kt │ │ ├── TypeParameters/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ └── 2.kt │ │ ├── ValueArguments/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ ├── 2.kt │ │ │ └── 3.kt │ │ ├── ValueParameters/ │ │ │ ├── 0.kt │ │ │ ├── 1.kt │ │ │ ├── 2.kt │ │ │ └── 3.kt │ │ └── WholeFile/ │ │ ├── 0.kt │ │ └── 1.kt │ └── selectPrevious/ │ ├── BlockStatements/ │ │ ├── 0.kt │ │ ├── 1.kt │ │ ├── 2.kt │ │ ├── 3.kt │ │ ├── 4.kt │ │ ├── 5.kt │ │ ├── 6.kt │ │ ├── 7.kt │ │ ├── 8.kt │ │ └── 9.kt │ ├── BlockStatementsWithWindowsDelimiter/ │ │ ├── 0.kt │ │ ├── 1.kt │ │ ├── 2.kt │ │ ├── 3.kt │ │ ├── 4.kt │ │ ├── 5.kt │ │ ├── 6.kt │ │ ├── 7.kt │ │ ├── 8.kt │ │ └── 9.kt │ ├── Classes/ │ │ ├── 0.kt │ │ ├── 1.kt │ │ ├── 2.kt │ │ ├── 3.kt │ │ └── 4.kt │ ├── DocComment/ │ │ ├── 0.kt │ │ ├── 1.kt │ │ ├── 2.kt │ │ ├── 3.kt │ │ └── 4.kt │ ├── FunctionWithLineComments/ │ │ ├── 0.kt │ │ ├── 1.kt │ │ ├── 2.kt │ │ ├── 3.kt │ │ └── 4.kt │ ├── Functions/ │ │ ├── 0.kt │ │ ├── 1.kt │ │ └── 2.kt │ ├── Imports/ │ │ ├── 0.kt │ │ ├── 1.kt │ │ ├── 2.kt │ │ ├── 3.kt │ │ ├── 4.kt │ │ ├── 5.kt │ │ ├── 6.kt │ │ └── 7.kt │ ├── NonTraversableElement/ │ │ ├── 0.kt │ │ ├── 1.kt │ │ └── 2.kt │ ├── ShiftOnWhitespace/ │ │ ├── 0.kt │ │ └── 1.kt │ ├── TemplateStringLiteral/ │ │ ├── 0.kt │ │ ├── 1.kt │ │ ├── 2.kt │ │ ├── 3.kt │ │ ├── 4.kt │ │ └── 5.kt │ ├── TypeArguments/ │ │ ├── 0.kt │ │ ├── 1.kt │ │ ├── 2.kt │ │ └── 3.kt │ ├── TypeParameters/ │ │ ├── 0.kt │ │ ├── 1.kt │ │ ├── 2.kt │ │ └── 3.kt │ ├── ValueArguments/ │ │ ├── 0.kt │ │ ├── 1.kt │ │ ├── 2.kt │ │ └── 3.kt │ ├── ValueParameters/ │ │ ├── 0.kt │ │ ├── 1.kt │ │ ├── 2.kt │ │ └── 3.kt │ └── WholeFile/ │ ├── 0.kt │ └── 1.kt ├── kotlin-weaving-feature/ │ ├── build.properties │ ├── feature.xml │ └── pom.xml ├── maven-build/ │ ├── maven-build-install-offline.launch │ ├── maven-build-install.launch │ └── maven-update-version.launch ├── pom.xml └── publish-new-version.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ **/testData/** linguist-vendored ================================================ FILE: .github/workflows/main.yml ================================================ name: kotlin-eclipse on: push: branches: [ "master" ] workflow_dispatch: jobs: build: runs-on: ubuntu-latest steps: - name: Checkout source code uses: actions/checkout@v3 - name: Set up JDK 17 uses: actions/setup-java@v3 with: java-version: '17' distribution: 'adopt' - name: Build with Maven run: mvn --batch-mode --nsu clean && mvn --batch-mode --update-snapshots clean validate -Pwith-gradle -pl kotlin-bundled-compiler && mvn --batch-mode --update-snapshots package - name: Publish eclipse repository uses: actions/upload-artifact@v3 with: name: kotlin-eclipse-plugin path: kotlin-eclipse-p2updatesite/target/kotlin-eclipse-plugin.zip ================================================ FILE: .gitignore ================================================ .DS_Store .gradle .idea .metadata .recommenders .gradletasknamecache bin build common_testData kotlin-eclipse-ui-test/lib kotlin-eclipse-gradle-model/lib target *.iml *.orig target/ .settings .classpath .project lib ================================================ FILE: LICENSE ================================================ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright 2013-2019 JetBrains s.r.o. and Kotlin for Eclipse project contributors. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: README.md ================================================ Kotlin for Eclipse ============== [![official JetBrains project](http://jb.gg/badges/official.svg)](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub) Welcome to Kotlin for Eclipse project! Some handy links: * [Kotlin Site](http://kotlinlang.org/) * [Getting Started Guide](http://kotlinlang.org/docs/tutorials/getting-started-eclipse.html) * [Kotlin on Eclipse Marketplace](https://marketplace.eclipse.org/content/kotlin-plugin-eclipse) * Issue Tracker: [File New Issue](https://youtrack.jetbrains.com/newIssue?project=KE&clearDraft=true), [All Open Issues](https://youtrack.jetbrains.com/issues/KE?q=%23Unresolved) * [Kotlin Blog](http://blog.jetbrains.com/kotlin/) * [Forum](https://discuss.kotlinlang.org/) * [TeamCity CI build](https://teamcity.jetbrains.com/viewType.html?buildTypeId=Kotlin_EclipsePlugin) * [Follow Kotlin on Twitter](https://twitter.com/kotlin) ### Installation To give it a try you will need a clean installation of Eclipse Neon or newer. The Kotlin plugin is available from the Eclipse Marketplace. The easiest way to install the Kotlin plugin is to **drag-and-drop this button into a running Eclipse window**: Drag to your running Eclipse workspace to install Kotlin Plugin for Eclipse Alternatively, you can use *Help -> Eclipse Marketplace�* menu, or the following update site: https://files.pkg.jetbrains.space/kotlin/p/kotlin-eclipse/main/last/ ### Building and Development *Eclipse IDE for Eclipse Committers* is the recommended way to build and develop the `kotlin-eclipse` project. Eclipse [Oxygen 4.7](https://www.eclipse.org/downloads/packages/eclipse-ide-eclipse-committers/oxygenr) is used so far. In order to start development in Eclipse: - Install the [AspectJ Eclipse plug-in for Eclipse 4.7](http://www.eclipse.org/ajdt/downloads/index.php). To install AJDT 2.2.4 use the following update site: http://download.eclipse.org/tools/ajdt/47/dev/update - Since Kotlin plugin contains code written in Kotlin itself, you will also need a Kotlin plugin to build the project in Eclipse. To install the Kotlin Eclipse plugin use the following update site: https://teamcity.jetbrains.com/guestAuth/repository/download/Kotlin_EclipsePlugin/bootstrap.tcbuildtag/ - Since Kotlin plugin uses weaving, you need to launch the project with weaving enabled. Installation of Equinox Weaving Launcher will add two additional launch configurations types for running plugin and for testing. To install the Equinox Weaving Launcher you can use the following update site: http://download.scala-ide.org/plugins/equinox-weaving-launcher/releases/site/ - Import plugin projects from the cloned repository into your workspace File -> Import -> Existing Projects into Workspace - Using the command line, run gradle build to download the Kotlin compiler. It will be used as a bundled compiler in built plugin and as a library during development. cd {repository}/kotlin-bundled-compiler ./gradlew clean getBundled or in Windows environment: cd {repository}\kotlin-bundled-compiler gradlew.bat clean getBundled - Run another instance of Eclipse with the Kotlin plugin inside kotlin-eclipse-ui -> Run As -> Eclipse Weaving enabled Eclipse Application Building from the command line is also available (Note that Maven **3.0.5** is required): cd {repository} mvn install ### Eclipse update sites Latest stable release: https://files.pkg.jetbrains.space/kotlin/p/kotlin-eclipse/main/last/ Any previously released version (replace *:version* with the version number): https://files.pkg.jetbrains.space/kotlin/p/kotlin-eclipse/main/:version/ Nightly build: https://teamcity.jetbrains.com/guestAuth/repository/download/Kotlin_EclipsePlugin/.lastSuccessful/ ### Kotlin Eclipse Plugin Developer Documentation See basic developer documentation [here](https://github.com/JetBrains/kotlin-eclipse/blob/master/docs/dev-documentation.md) ================================================ FILE: common-settings/kotlin-formatting.xml ================================================ ================================================ FILE: docs/dev-documentation.md ================================================ # Kotlin Eclipse Plugin Developer Documentation ## Kotlin Eclipse plugins overview Kotlin plugin consists of several plugins, here is a short description for each of them: - `kotlin-bundled-compiler`: This plugin is used as a dependency for all other plugins, it exports main jars to work with Kotlin (`kotlin-compiler.jar`, `kotlin-ide-common.jar`...). Kotlin compiler will be used as the bundled compiler in the built plugin and as a library during development. Also, `kotlin-bundled-compiler` plugin contains several helper classes for IDE-features (such as formatter) that are coming from IntelliJ IDEA. - `kotlin-eclipse-aspects`: This plugin provides several aspects to weave into Eclipse and JDT internals. - `kotlin-eclipse-core`: This plugin is used to interact with the Kotlin compiler to configure it and provide such features as analysis, compilation and interoperability with Java. - `kotlin-eclipse-maven`: This plugin depends on `m2e` plugin and provides functionality to configure maven project with Kotlin. - `kotlin-eclipse-ui`: This plugin provides IDE features through the standard Eclipse and JDT extension points. - `kotlin-eclipse-test-framework`: This plugin contains useful utils and mock classes to write tests - `kotlin-eclipse-ui-test`: This plugin contains functional tests for IDE features #### Interoperability with JDT Existing Java code can be called from Kotlin in a natural way, and Kotlin code can be used from Java. Java code in Eclipse should understand Kotlin. Features such as navigation, refactorings, find usages, and others should work together with Kotlin and Java. ##### Light classes Note that Kotlin does not have a presentation compiler, like Java or Scala. Instead of this, the Kotlin plugin generates so called "light class files": Kotlin source code translated to bytecode declarations without bodies. Each project with Kotlin in Eclipse depends on `KOTLIN_CONTAINER` (see [`KotlinClasspathContainer`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/KotlinClasspathContainer.kt)) which contains `kotlin-stdlib.jar`, `kotlin-reflect.jar` and a folder with light classfiles (`kotlin_bin`). Light classes are stored only in virtual memory and are managed by a special file system (see [`KotlinFileSystem`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/filesystem/KotlinFileSystem.java) , [`KotlinFileStore`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/filesystem/KotlinFileStore.kt)), so they do not affect the runtime. Let us describe what is happening on each file save. On each file save Eclipse triggers Kotlin builder, then the method [`KotlinLightClassGeneration.updateLightClasses()`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/asJava/KotlinLightClassGeneration.kt) is called which takes affected files and computes names of class files that can be created from the affected source files. If we don't find a light class in our cache, we create a new empty class file in our file system. If file exists, we touch that file. After this, Eclipse determines that some class files on the classpath were added or changed which triggers reindex for those files by calling method [`KotlinFileStore.openInputStream`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/filesystem/KotlinFileStore.kt#L46). This method generates bytecode for the light class by calling the Kotlin compiler in special mode ([`KotlinLightClassGeneration.buildLightClasses`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/asJava/KotlinLightClassGeneration.kt#L43)). Basically, this allows Java to see Kotlin sources as special binary dependency. ##### Light classes to Kotlin source code Existence of light classes allows to call Kotlin code from Java in Eclipse, but to navigate from Java to Kotlin source code we have to map light classes to the source code. Otherwise we would navigate to the binary code. Unfortunately, Eclipse JDT does not provide any extension point to handle such case, and to do so, we use aspects to weave into Java navigation mechanism. We provide a simple aspect ([`KotlinOpenEditorAspect.aj`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-aspects/src/org/jetbrains/kotlin/aspects/navigation/KotlinOpenEditorAspect.aj)), which weaves into `org.eclipse.jdt.internal.ui.javaeditor.EditorUtility.openInEditor` method and checks input element. If this element belongs to our special file system, then we are trying to find corresponding source element in Kotlin and navigate to it. ### Editor Actions Kotlin plugin provides editors for usual Kotlin files (`.kt`), Kotlin script files (`.kts`) and Kotlin binary files (`.class` files). Each editor implements common interface [`KotlinEditor`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinEditor.kt). Editors for Kotlin files and script files also implement [`KotlinCommonEditor`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinCommonEditor.kt). [`KotlinCommonEditor`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinCommonEditor.kt) extends Java editor (`CompilationUnitEditor`) and provides own editor actions (see [`createActions`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinCommonEditor.kt#L108)) #### Organize imports action example As an example of editor action let's consider how organize imports works. Organize imports action is registered in [`createActions`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/KotlinCommonEditor.kt#L145) method with the corresponding action ID. As we reuse the Java editor, we don't have to set up shortcuts, they will be the same as for Java editor. The main method for this action is [`KotlinOrganizeImportsAction.run`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/organizeImports/KotlinOrganizeImportsAction.kt#L59). First of all, it collects missing imports, adds them to the existing imports and then runs [`KotlinOrganizeImportsAction.optimizeImports`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/organizeImports/KotlinOrganizeImportsAction.kt#L86). This method removes duplicates and unused imports, reorganizes imports and replaces some explicit imports with the star import. The important part here is that we reuse the code to optimize imports from the Kotlin plugin for IntelliJ IDEA. The original method that is called from the Eclipse plugin is [`buildOptimizedImports`](https://github.com/JetBrains/kotlin/blob/master/idea/ide-common/src/org/jetbrains/kotlin/idea/util/OptimizedImportsBuilder.kt#L87), which is also used in the plugin for IDEA. #### Code reuse from the IDEA plugin Eclipse plugin depends on `kotlin-ide-common.jar` artifact, which provides common functionality for IDEA and Eclipse plugin. Basically, this is a module ([`ide-common`](https://github.com/JetBrains/kotlin/tree/master/idea/ide-common)) in Kotlin project with minimum dependencies, so it can be used in Eclipse or Netbeans plugin. This module provides several features that are used across the Eclipse plugin. For example, completion in the Eclipse plugin mostly reuses parts of completion from the IDEA plugin ([`KotlinCompletionUtils.getReferenceVariants`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/completion/KotlinCompletionUtils.kt#L84) uses [`ReferenceVarianceHelper`](https://github.com/JetBrains/kotlin/blob/master/idea/ide-common/src/org/jetbrains/kotlin/idea/codeInsight/ReferenceVariantsHelper.kt)). Generally, it's a preferable way to implement features in the Eclipse plugin, i.e. to reuse parts from the IDEA plugin. Unfortunately, there is no common way to do this because of different models of IDEs. ### Kotlin compilation and launch Kotlin Eclipse plugin does not support incremental compilation or presentation compiler. Kotlin files are compiled using the Kotlin compiler in [`KotlinCompiler.compileKotlinFiles`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/compiler/KotlinCompiler.java#L48). #### Kotlin Builder Kotlin plugin uses the Eclipse builder concept to track changes and compile Kotlin files if needed. For a usual change in project, Kotlin builder only updates light classes. Then, if project is being built to launch the application ([`KotlinBuilder.isBuildingForLaunch`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/builder/KotlinBuilder.kt#L180)), Kotlin builder compiles Kotlin files (in [`KotlinBuilder.build`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/builder/KotlinBuilder.kt#L63)). Therefore, Kotlin builder should always precede Java builder. #### Kotlin Nature There is a Kotlin [nature](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinNature.kt) to mark Kotlin projects. #### Kotlin Debugger Kotlin Eclipse plugin is using the standard debugger for Java in Eclipse. For example, there are [`KotlinToggleBreakpointAdapter`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/debug/KotlinToggleBreakpointAdapter.kt) and [`KotlinRunToLineAdapter`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/debug/KotlinRunToLineAdapter.kt) adapters to add breakpoint to a specific line and to support action "run to cursor". ### Kotlin environment and project analysis In order to analyse files and use compiler API, [`KotlinEnvironment`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinEnvironment.kt#L207) have to be configured. Basically, `KotlinEnvironment` is created for each project in Eclipse and maps external (from Eclipse) project model to the internal one. Also, it registers various services and configures dependencies, see [`KotlinEnvironment.configureClasspath`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinEnvironment.kt#L231). Important note: if classpath was changed, corresponding Kotlin environment should be recreated. #### Kotlin parsing There are PSI and Kt elements that are basically represent concrete syntax tree of Kotlin program. (The term "PSI" is used in IntelliJ IDEA to refer to the syntax tree, and stands for "Program Structure Interface".) To get the parsed version of a source file [`KotlinPsiManager`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/builder/KotlinPsiManager.kt) should be used. Note that it caches last version of `KtFile`, so to get actual `KtFile`, source code of file can be explicitly passed to the [`getKotlinFileIfExist`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/builder/KotlinPsiManager.kt#L368) method, or you can use [`commitFile`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/builder/KotlinPsiManager.kt#L389) to reparse and cache changed file. #### "Remove explicit type" quick assist example Let's consider how "Remove explicit type" quick assist works. This quick assist removes explicitly written type reference for property, function and loop parameter, i.e. it converts `val s: String = "value"` to `val s = "value"`. First of all, when user invokes quick assist on some element (`ctrl+1`), method [`KotlinQuickAssist.isApplicable`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinQuickAssist.kt#L32) is called. `isApplicable` method obtains current PSI element ([`getActiveElement`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinQuickAssist.kt#L37)), it gets PSI file and then calls `findElementAt` to get concrete element at specific offset. Once we get active PSI element, we pass it to our quick assists and check for theirs applicability. [`KotlinRemoveExplicitTypeAssistProposal.isApplicable`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinRemoveExplicitTypeAssistProposal.kt#L35) checks that active PSI element is actually a property, function or loop parameter with a type reference. In method [`KotlinRemoveExplicitTypeAssistProposal.apply`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/quickassist/KotlinRemoveExplicitTypeAssistProposal.kt#L62) quick assist is executed and removes corresponding type reference. This and other quick assists and actions rely completely on the knowledge of CST for Kotlin. In order to make it easier, there is an action "View Psi Structure for Current File" in the context menu for Kotlin file, which can be used to examine structure of the Kotlin CST. #### Kotlin analyzer Many features in IDE requires more deep knowledge of the Kotlin compiler implementation. For example, [`KotlinLineAnnotationsReconciler`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/annotations/AnnotationManager.kt#L146) is used to show diagnostics from the compiler. It uses concept of `ReconcilingStrategy` and runs after each change in active file, when analysis results for the file will be ready and cached. The main line there is `KotlinAnalyzer.analyzeFile(file)...`, which returns analysis results and can be used to get diagnostics from the compiler. Kotlin compiler uses map called `BindingContext` to contain all types and internal representations (descriptors) for expressions in program. To get binding context one can use [`KotlinAnalyzer.analyzeFile(file).bindingContext`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/KotlinAnalyzer.kt#L26). See [`KotlinSemanticHighlighter`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/highlighting/KotlinSemanticHighlighting.kt) for an example of the compiler analysis use. There are several methods in [`KotlinSemanticHighlightingVisitor`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/highlighting/KotlinSemanticHighlightingVisitor.kt), which uses binding context to obtain information either from a declaration ([`visitProperty`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/highlighting/KotlinSemanticHighlightingVisitor.kt#L123)), or from a reference ([`visitSimpleNameExpression`](https://github.com/JetBrains/kotlin-eclipse/blob/master/kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/highlighting/KotlinSemanticHighlightingVisitor.kt#L82)). ================================================ FILE: kotlin-bundled-compiler/Get Bundled Kotlin.launch ================================================ ================================================ FILE: kotlin-bundled-compiler/META-INF/MANIFEST.MF ================================================ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: Bundled Kotlin Compiler Bundle-SymbolicName: org.jetbrains.kotlin.bundled-compiler;singleton:=true Bundle-Version: 0.8.24.qualifier Bundle-Vendor: JetBrains Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-ClassPath: ., lib/ide-common.jar, lib/kotlin-compiler.jar, lib/ide-dependencies.jar, lib/kotlin-stdlib.jar, lib/kotlin-plugin-parts.jar, lib/kotlin-script-runtime.jar, lib/kotlin-scripting-compiler.jar, lib/kotlin-formatter.jar, lib/kotlin-common.jar, lib/kotlin-core.jar, lib/kotlin-idea.jar, lib/kotlin-j2k-old.jar, lib/kotlin-j2k-new.jar, lib/kotlin-j2k-idea.jar, lib/kotlin-j2k-services.jar, lib/kotlin-frontend-independent.jar, lib/kotlin-reflect.jar, ../kotlin-eclipse-ui-test/lib/gson-2.3.1.jar, lib/annotations-13.0.jar, lib/kotlin-scripting-compiler-impl.jar, lib/kotlin-scripting-common.jar, lib/kotlin-scripting-jvm.jar, lib/kotlinx-coroutines-core.jar Export-Package: com.google.common.collect, com.intellij, org.jetbrains.kotlin.idea.util.application, org.jetbrains.kotlin.idea.caches.resolve, org.jetbrains.kotlin.idea.core.util, org.jetbrains.kotlin.nj2k, org.jetbrains.kotlin.idea.j2k, org.jetbrains.kotlin.nj2k.postProcessing, com.intellij.codeInsight, com.intellij.codeInsight.completion.scope, com.intellij.codeInsight.folding, com.intellij.codeInsight.folding.impl, com.intellij.codeInsight.javadoc, com.intellij.codeInsight.runner, com.intellij.core, com.intellij.diagnostic, com.intellij.extapi.psi, com.intellij.formatting, com.intellij.icons, com.intellij.ide, com.intellij.ide.highlighter, com.intellij.ide.plugins, com.intellij.ide.util, com.intellij.injected.editor, com.intellij.lang, com.intellij.lang.folding, com.intellij.lang.impl, com.intellij.lang.injection, com.intellij.lang.java, com.intellij.lang.java.lexer, com.intellij.lang.java.parser, com.intellij.lang.jvm, com.intellij.lang.jvm.facade, com.intellij.lexer, com.intellij.mock, com.intellij.navigation, com.intellij.openapi, com.intellij.openapi.application, com.intellij.openapi.application.ex, com.intellij.openapi.application.impl, com.intellij.openapi.command, com.intellij.openapi.command.impl, com.intellij.openapi.command.undo, com.intellij.openapi.components, com.intellij.openapi.diagnostic, com.intellij.openapi.editor, com.intellij.openapi.editor.actionSystem, com.intellij.openapi.editor.colors, com.intellij.openapi.editor.event, com.intellij.openapi.editor.ex, com.intellij.openapi.editor.impl, com.intellij.openapi.editor.impl.event, com.intellij.openapi.editor.markup, com.intellij.openapi.extensions, com.intellij.openapi.extensions.impl, com.intellij.openapi.fileEditor, com.intellij.openapi.fileEditor.impl, com.intellij.openapi.fileTypes, com.intellij.openapi.module, com.intellij.openapi.progress, com.intellij.openapi.project, com.intellij.openapi.projectRoots, com.intellij.openapi.roots, com.intellij.openapi.ui, com.intellij.openapi.util, com.intellij.openapi.util.io, com.intellij.openapi.util.objectTree, com.intellij.openapi.util.registry, com.intellij.openapi.util.text, com.intellij.openapi.vfs, com.intellij.openapi.vfs.encoding, com.intellij.openapi.vfs.ex, com.intellij.openapi.vfs.impl, com.intellij.openapi.vfs.impl.jar, com.intellij.openapi.vfs.local, com.intellij.openapi.vfs.newvfs, com.intellij.openapi.vfs.newvfs.events, com.intellij.openapi.vfs.pointers, com.intellij.patterns, com.intellij.patterns.compiler, com.intellij.pom, com.intellij.pom.event, com.intellij.pom.impl, com.intellij.pom.java, com.intellij.pom.tree, com.intellij.pom.tree.events, com.intellij.pom.tree.events.impl, com.intellij.psi, com.intellij.psi.augment, com.intellij.psi.codeStyle, com.intellij.psi.compiled, com.intellij.psi.controlFlow, com.intellij.psi.css, com.intellij.psi.filters, com.intellij.psi.filters.classes, com.intellij.psi.filters.element, com.intellij.psi.filters.position, com.intellij.psi.formatter, com.intellij.psi.impl, com.intellij.psi.impl.cache, com.intellij.psi.impl.compiled, com.intellij.psi.impl.file, com.intellij.psi.impl.file.impl, com.intellij.psi.impl.java.stubs, com.intellij.psi.impl.java.stubs.impl, com.intellij.psi.impl.java.stubs.index, com.intellij.psi.impl.light, com.intellij.psi.impl.meta, com.intellij.psi.impl.smartPointers, com.intellij.psi.impl.source, com.intellij.psi.impl.source.codeStyle, com.intellij.psi.impl.source.javadoc, com.intellij.psi.impl.source.resolve, com.intellij.psi.impl.source.resolve.graphInference, com.intellij.psi.impl.source.resolve.graphInference.constraints, com.intellij.psi.impl.source.resolve.reference, com.intellij.psi.impl.source.resolve.reference.impl, com.intellij.psi.impl.source.resolve.reference.impl.manipulators, com.intellij.psi.impl.source.resolve.reference.impl.providers, com.intellij.psi.impl.source.tree, com.intellij.psi.impl.source.tree.injected, com.intellij.psi.impl.source.tree.java, com.intellij.psi.infos, com.intellij.psi.javadoc, com.intellij.psi.meta, com.intellij.psi.presentation.java, com.intellij.psi.scope, com.intellij.psi.scope.conflictResolvers, com.intellij.psi.scope.processor, com.intellij.psi.scope.util, com.intellij.psi.search, com.intellij.psi.search.searches, com.intellij.psi.stubs, com.intellij.psi.targets, com.intellij.psi.templateLanguages, com.intellij.psi.text, com.intellij.psi.tree, com.intellij.psi.tree.java, com.intellij.psi.util, com.intellij.reference, com.intellij.testFramework, com.intellij.ui, com.intellij.util, com.intellij.util.cls, com.intellij.util.codeInsight, com.intellij.util.concurrency, com.intellij.util.containers, com.intellij.util.containers.hash, com.intellij.util.diff, com.intellij.util.execution, com.intellij.util.graph, com.intellij.util.indexing, com.intellij.util.io, com.intellij.util.keyFMap, com.intellij.util.lang, com.intellij.util.messages, com.intellij.util.messages.impl, com.intellij.util.pico, com.intellij.util.text, com.intellij.util.xmlb, com.intellij.util.xmlb.annotations, gnu.trove, kotlin, kotlin.collections, kotlin.comparisons, kotlin.concurrent, kotlin.coroutines, kotlin.coroutines.intrinsics, kotlin.coroutines.jvm.internal, kotlin.internal;x-internal:=true, kotlin.io, kotlin.jvm, kotlin.jvm.functions, kotlin.jvm.internal;x-internal:=true, kotlin.jvm.internal.unsafe;x-internal:=true, kotlin.properties, kotlin.ranges, kotlin.reflect, kotlin.reflect.full, kotlin.reflect.jvm.internal.impl.load.kotlin, kotlin.script.dependencies, kotlin.script.experimental.annotations, kotlin.script.experimental.api, kotlin.script.experimental.dependencies, kotlin.script.experimental.host, kotlin.script.experimental.jvm, kotlin.script.experimental.util, kotlin.script.extensions, kotlin.script.templates, kotlin.script.templates.standard, kotlin.sequences, kotlin.text, kotlinx.coroutines, org.jetbrains.annotations, org.jetbrains.kotlin, org.jetbrains.kotlin.analyzer, org.jetbrains.kotlin.analyzer.common, org.jetbrains.kotlin.asJava, org.jetbrains.kotlin.asJava.classes, org.jetbrains.kotlin.asJava.finder, org.jetbrains.kotlin.backend.common, org.jetbrains.kotlin.backend.common.bridges, org.jetbrains.kotlin.backend.common.output, org.jetbrains.kotlin.builtins, org.jetbrains.kotlin.builtins.jvm, org.jetbrains.kotlin.caches.resolve, org.jetbrains.kotlin.cfg, org.jetbrains.kotlin.cfg.pseudocode, org.jetbrains.kotlin.cfg.pseudocode.instructions, org.jetbrains.kotlin.cfg.pseudocode.instructions.eval, org.jetbrains.kotlin.cfg.pseudocode.instructions.jumps, org.jetbrains.kotlin.cfg.pseudocode.instructions.special, org.jetbrains.kotlin.cfg.pseudocodeTraverser, org.jetbrains.kotlin.checkers, org.jetbrains.kotlin.checkers.diagnostics, org.jetbrains.kotlin.checkers.diagnostics.factories, org.jetbrains.kotlin.checkers.utils, org.jetbrains.kotlin.cli.common, org.jetbrains.kotlin.cli.common.arguments, org.jetbrains.kotlin.cli.common.messages, org.jetbrains.kotlin.cli.common.modules, org.jetbrains.kotlin.cli.js, org.jetbrains.kotlin.cli.jvm, org.jetbrains.kotlin.cli.jvm.compiler, org.jetbrains.kotlin.cli.jvm.index, org.jetbrains.kotlin.codegen, org.jetbrains.kotlin.codegen.binding, org.jetbrains.kotlin.codegen.context, org.jetbrains.kotlin.codegen.extensions, org.jetbrains.kotlin.codegen.inline, org.jetbrains.kotlin.codegen.intrinsics, org.jetbrains.kotlin.codegen.optimization, org.jetbrains.kotlin.codegen.optimization.boxing, org.jetbrains.kotlin.codegen.optimization.common, org.jetbrains.kotlin.codegen.optimization.transformer, org.jetbrains.kotlin.codegen.signature, org.jetbrains.kotlin.codegen.state, org.jetbrains.kotlin.codegen.when, org.jetbrains.kotlin.compiler.plugin, org.jetbrains.kotlin.config, org.jetbrains.kotlin.container, org.jetbrains.kotlin.context, org.jetbrains.kotlin.contracts, org.jetbrains.kotlin.descriptors, org.jetbrains.kotlin.descriptors.annotations, org.jetbrains.kotlin.descriptors.impl, org.jetbrains.kotlin.descriptors.java, org.jetbrains.kotlin.diagnostics, org.jetbrains.kotlin.diagnostics.rendering, org.jetbrains.kotlin.extensions, org.jetbrains.kotlin.fileClasses, org.jetbrains.kotlin.frontend.di, org.jetbrains.kotlin.frontend.java.di, org.jetbrains.kotlin.idea, org.jetbrains.kotlin.idea.codeInsight, org.jetbrains.kotlin.idea.core.formatter, org.jetbrains.kotlin.idea.formatter, org.jetbrains.kotlin.idea.imports, org.jetbrains.kotlin.idea.kdoc, org.jetbrains.kotlin.idea.resolve, org.jetbrains.kotlin.idea.util, org.jetbrains.kotlin.incremental, org.jetbrains.kotlin.incremental.components, org.jetbrains.kotlin.j2k, org.jetbrains.kotlin.js.resolve.diagnostics, org.jetbrains.kotlin.kdoc.lexer, org.jetbrains.kotlin.kdoc.parser, org.jetbrains.kotlin.kdoc.psi.api, org.jetbrains.kotlin.kdoc.psi.impl, org.jetbrains.kotlin.lexer, org.jetbrains.kotlin.load.java, org.jetbrains.kotlin.load.java.components, org.jetbrains.kotlin.load.java.descriptors, org.jetbrains.kotlin.load.java.lazy, org.jetbrains.kotlin.load.java.lazy.descriptors, org.jetbrains.kotlin.load.java.lazy.types, org.jetbrains.kotlin.load.java.sam, org.jetbrains.kotlin.load.java.sources, org.jetbrains.kotlin.load.java.structure, org.jetbrains.kotlin.load.java.structure.impl, org.jetbrains.kotlin.load.java.typeEnhancement, org.jetbrains.kotlin.load.kotlin, org.jetbrains.kotlin.load.kotlin.header, org.jetbrains.kotlin.load.kotlin.incremental, org.jetbrains.kotlin.metadata.jvm.deserialization, org.jetbrains.kotlin.name, org.jetbrains.kotlin.parsing, org.jetbrains.kotlin.platform, org.jetbrains.kotlin.platform.jvm, org.jetbrains.kotlin.progress, org.jetbrains.kotlin.psi, org.jetbrains.kotlin.psi.addRemoveModifier, org.jetbrains.kotlin.psi.codeFragmentUtil, org.jetbrains.kotlin.psi.debugText, org.jetbrains.kotlin.psi.findDocComment, org.jetbrains.kotlin.psi.psiUtil, org.jetbrains.kotlin.psi.stubs, org.jetbrains.kotlin.psi.stubs.elements, org.jetbrains.kotlin.psi.stubs.impl, org.jetbrains.kotlin.psi.typeRefHelpers, org.jetbrains.kotlin.renderer, org.jetbrains.kotlin.resolve, org.jetbrains.kotlin.resolve.annotations, org.jetbrains.kotlin.resolve.bindingContextUtil, org.jetbrains.kotlin.resolve.calls, org.jetbrains.kotlin.resolve.calls.callUtil, org.jetbrains.kotlin.resolve.calls.checkers, org.jetbrains.kotlin.resolve.calls.context, org.jetbrains.kotlin.resolve.calls.inference, org.jetbrains.kotlin.resolve.calls.inference.constraintPosition, org.jetbrains.kotlin.resolve.calls.model, org.jetbrains.kotlin.resolve.calls.results, org.jetbrains.kotlin.resolve.calls.smartcasts, org.jetbrains.kotlin.resolve.calls.tasks, org.jetbrains.kotlin.resolve.calls.util, org.jetbrains.kotlin.resolve.checkers, org.jetbrains.kotlin.resolve.constants, org.jetbrains.kotlin.resolve.constants.evaluate, org.jetbrains.kotlin.resolve.deprecation, org.jetbrains.kotlin.resolve.descriptorUtil, org.jetbrains.kotlin.resolve.diagnostics, org.jetbrains.kotlin.resolve.extensions, org.jetbrains.kotlin.resolve.jvm, org.jetbrains.kotlin.resolve.jvm.diagnostics, org.jetbrains.kotlin.resolve.jvm.extensions, org.jetbrains.kotlin.resolve.jvm.jvmSignature, org.jetbrains.kotlin.resolve.jvm.kotlinSignature, org.jetbrains.kotlin.resolve.jvm.modules, org.jetbrains.kotlin.resolve.jvm.platform, org.jetbrains.kotlin.resolve.lazy, org.jetbrains.kotlin.resolve.lazy.data, org.jetbrains.kotlin.resolve.lazy.declarations, org.jetbrains.kotlin.resolve.lazy.descriptors, org.jetbrains.kotlin.resolve.sam, org.jetbrains.kotlin.resolve.scopes, org.jetbrains.kotlin.resolve.scopes.receivers, org.jetbrains.kotlin.resolve.scopes.utils, org.jetbrains.kotlin.resolve.source, org.jetbrains.kotlin.resolve.typeBinding, org.jetbrains.kotlin.scripting.configuration, org.jetbrains.kotlin.scripting.definitions, org.jetbrains.kotlin.scripting.extensions, org.jetbrains.kotlin.scripting.resolve, org.jetbrains.kotlin.serialization, org.jetbrains.kotlin.serialization.builtins, org.jetbrains.kotlin.serialization.deserialization, org.jetbrains.kotlin.serialization.deserialization.builtins, org.jetbrains.kotlin.serialization.deserialization.descriptors, org.jetbrains.kotlin.storage, org.jetbrains.kotlin.synthetic, org.jetbrains.kotlin.types, org.jetbrains.kotlin.types.checker, org.jetbrains.kotlin.types.error, org.jetbrains.kotlin.types.expressions, org.jetbrains.kotlin.types.typeUtil, org.jetbrains.kotlin.types.typesApproximation, org.jetbrains.kotlin.util, org.jetbrains.kotlin.util.collectionUtils, org.jetbrains.kotlin.util.slicedMap, org.jetbrains.kotlin.utils, org.jetbrains.kotlin.utils.addToStdlib, org.jetbrains.kotlin.utils.concurrent.block, org.jetbrains.kotlin.utils.fileUtils, org.jetbrains.kotlin.utils.intellij, org.jetbrains.kotlin.utils.strings, org.jetbrains.org.objectweb.asm, org.jetbrains.org.objectweb.asm.commons, org.jetbrains.org.objectweb.asm.signature, org.jetbrains.org.objectweb.asm.tree, org.jetbrains.org.objectweb.asm.tree.analysis, org.jetbrains.org.objectweb.asm.util ================================================ FILE: kotlin-bundled-compiler/build.gradle.kts ================================================ import com.intellij.buildsupport.dependencies.PackageListFromSimpleFile import com.intellij.buildsupport.resolve.http.HttpArtifact import com.intellij.buildsupport.resolve.http.HttpArtifactsResolver import com.intellij.buildsupport.resolve.http.idea.IntellijIdeaArtifactsResolver import com.intellij.buildsupport.utils.FileUtils apply(plugin = "base") // constants val teamcityBaseUrl ="https://teamcity.jetbrains.com" val ideaSdkUrl = "https://www.jetbrains.com/intellij-repository/releases/com/jetbrains/intellij/idea" // properties that might/should be modifiable //val kotlinCompilerTcBuildId: String = project.findProperty("kotlinCompilerTcBuildId") as String? ?: "3546752" val kotlinPluginUpdateId = project.findProperty("kotlinPluginUpdateId") as String? ?: "169248" // Kotlin Plugin 1.6.21 for Idea 2021.3 val kotlinCompilerVersion: String = project.findProperty("kotlinCompilerVersion") as String? ?: "1.6.21" val kotlinxVersion: String = project.findProperty("kolinxVersion") as String? ?: "1.5.2" val tcArtifactsPath: String = project.findProperty("tcArtifactsPath") as String? ?: "" val ideaVersion: String = project.findProperty("ideaVersion") as String? ?: "213.5744.223" //Idea 2021.3 val kotlinIdeaCompatibleVersionMinor: String = project.findProperty("kotlinIdeaCompatibleVersionMinor") as String? ?: "2021.3" val ignoreSources: Boolean = true//project.hasProperty("ignoreSources") //directories val testDataDir = file("${projectDir.parentFile}/kotlin-eclipse-ui-test/common_testData") //TODO later refactor to the proper project dir val testModuleLibDir = file("${projectDir.parentFile}/kotlin-eclipse-ui-test/lib") //TODO later refactor to the proper project dir val downloadDirName = "downloads$ideaVersion-$kotlinCompilerVersion" val teamCityWorkingDir = project.findProperty("teamcity.buildsupport.workingDir") val libDir = if (teamCityWorkingDir != null) file("$teamCityWorkingDir/lib") else file("lib") val localTCArtifacts: Boolean = tcArtifactsPath.isNotBlank() val downloadDir = if(localTCArtifacts) file(tcArtifactsPath) else file("$libDir/$downloadDirName") /*val tcArtifactsResolver = KotlinCompilerTCArtifactsResolver(teamcityBaseUrl, project.hasProperty("lastSuccessfulBuild"), kotlinCompilerTcBuildId, kotlinCompilerVersion, kotlinIdeaCompatibleVersionMinor)*/ HttpArtifactsResolver.getProxyProps()["https.proxyHost"] = project.findProperty("https.proxyHost") ?: System.getProperty("https.proxyHost") HttpArtifactsResolver.getProxyProps()["https.proxyPort"] = project.findProperty("https.proxyPort") ?: System.getProperty("https.proxyPort") HttpArtifactsResolver.getProxyProps()["https.proxyUser"] = project.findProperty("https.proxyUser") ?: System.getProperty("https.proxyUser") HttpArtifactsResolver.getProxyProps()["https.proxyPassword"] = project.findProperty("https.proxyPassword") ?: System.getProperty("https.proxyPassword") val ideaArtifactsResolver = IntellijIdeaArtifactsResolver(ideaSdkUrl, ideaVersion) val kotlinPluginArtifactsResolver = HttpArtifactsResolver("https://plugins.jetbrains.com") val tempKotlinHttpArtifact = HttpArtifact("plugin/download?rel=true&updateId=$kotlinPluginUpdateId") tasks.withType { gradleVersion = "5.5.1" } val testFrameworkDependencies by configurations.creating val kotlinxLibraries by configurations.creating dependencies { testFrameworkDependencies("com.google.code.gson:gson:2.3.1") kotlinxLibraries("org.jetbrains.kotlinx:kotlinx-coroutines-core:$kotlinxVersion") { isTransitive = false } kotlinxLibraries("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:$kotlinxVersion") { isTransitive = false } } repositories { mavenCentral() } tasks.named("clean") { doLast { FileUtils.cleanDir(testDataDir) FileUtils.cleanDir(testModuleLibDir) FileUtils.cleanDirExceptSubDirName(libDir, downloadDirName) } } val deleteLibrariesFromLibFolder by tasks.registering { doFirst { libDir.listFiles()?.filter { it.isFile }?.forEach { it.deleteRecursively() } } } val downloadTestData by tasks.registering { val locallyDownloadedTestDataFile by extra { if(localTCArtifacts){ file("$tcArtifactsPath/kotlin-test-data.zip") } else { file("$testDataDir/kotlin-test-data.zip") } } doLast { //TODO can we get the test data from somewhere? if (!localTCArtifacts && !locallyDownloadedTestDataFile.exists()) { //tcArtifactsResolver.downloadTo(tcArtifactsResolver.KOTLIN_TEST_DATA_ZIP, locallyDownloadedTestDataFile) } /*copy { from(zipTree(locallyDownloadedTestDataFile)) into(testDataDir) }*/ } } val downloadTestFrameworkDependencies by tasks.registering(Copy::class) { from(testFrameworkDependencies) into(testModuleLibDir) } val downloadKotlinCompilerPluginAndExtractSelectedJars by tasks.registering { dependsOn(deleteLibrariesFromLibFolder) val kotlinDownloadDir = file("$downloadDir/kotlin-$kotlinCompilerVersion/$kotlinIdeaCompatibleVersionMinor") val locallyDownloadedCompilerFile by extra { file(kotlinDownloadDir).listFiles()?.firstOrNull { it.name.startsWith("kotlin-plugin-") } ?: file("$kotlinDownloadDir/kotlin-plugin.zip") } doLast { if (!localTCArtifacts && !locallyDownloadedCompilerFile.exists()) { kotlinPluginArtifactsResolver.downloadTo(tempKotlinHttpArtifact, locallyDownloadedCompilerFile) //tcArtifactsResolver.downloadTo(tcArtifactsResolver.KOTLIN_PLUGIN_ZIP, locallyDownloadedCompilerFile) } copy { from(zipTree(locallyDownloadedCompilerFile)) setIncludes(setOf("Kotlin/lib/kotlin-plugin.jar", "Kotlin/lib/ide-common.jar", "Kotlin/lib/kotlin-core.jar", "Kotlin/lib/kotlin-idea.jar", "Kotlin/lib/kotlin-common.jar", "Kotlin/lib/kotlin-j2k-old.jar", "Kotlin/lib/kotlin-j2k-new.jar", "Kotlin/lib/kotlin-j2k-idea.jar", "Kotlin/lib/kotlin-j2k-services.jar", "Kotlin/lib/kotlin-frontend-independent.jar", "Kotlin/lib/kotlin-formatter.jar", "Kotlin/kotlinc/lib/kotlin-compiler.jar", "Kotlin/kotlinc/lib/kotlin-stdlib.jar", "Kotlin/kotlinc/lib/kotlin-reflect.jar", "Kotlin/kotlinc/lib/kotlin-script-runtime.jar", "Kotlin/kotlinc/lib/kotlin-scripting-compiler.jar", "Kotlin/kotlinc/lib/kotlin-scripting-common.jar", "Kotlin/kotlinc/lib/kotlin-scripting-jvm.jar", "Kotlin/kotlinc/lib/kotlin-scripting-compiler-impl.jar", "Kotlin/kotlinc/lib/kotlin-jdk-annotations.jar", "Kotlin/kotlinc/lib/kotlin-stdlib-sources.jar", "Kotlin/kotlinc/lib/allopen-compiler-plugin.jar", "Kotlin/kotlinc/lib/noarg-compiler-plugin.jar", "Kotlin/kotlinc/lib/sam-with-receiver-compiler-plugin.jar", "Kotlin/kotlinc/lib/annotations-13.0.jar")) includeEmptyDirs = false into(libDir) // flatten + rename eachFile { this.relativePath = RelativePath(true, this.name) } } } } val extractPackagesFromPlugin by tasks.registering(Jar::class) { dependsOn(downloadKotlinCompilerPluginAndExtractSelectedJars) from(zipTree("$libDir/kotlin-plugin.jar")) destinationDirectory.set(libDir) archiveFileName.set("kotlin-plugin-parts.jar") include("**") exclude("com/intellij/util/**") doLast { file("$libDir/kotlin-plugin.jar").delete() } } val extractPackagesFromKTCompiler by tasks.registering(Jar::class) { dependsOn(downloadKotlinCompilerPluginAndExtractSelectedJars) from(zipTree("$libDir/kotlin-compiler.jar")) destinationDirectory.set(libDir) archiveFileName.set("kotlin-compiler-tmp.jar") include("**") exclude("com/intellij/openapi/util/text/**") exclude("com/intellij/util/containers/MultiMap*") doLast { file("$libDir/kotlin-compiler.jar").delete() file("$libDir/kotlin-compiler-tmp.jar").renameTo(file("$libDir/kotlin-compiler.jar")) } } val downloadIntellijCoreAndExtractSelectedJars by tasks.registering { dependsOn(deleteLibrariesFromLibFolder) val ideaDownloadDir = file("$downloadDir/idea-$ideaVersion") val locallyDownloadedIntellijCoreFile by extra { file("$ideaDownloadDir/intellij-core.zip") } doLast { if(!locallyDownloadedIntellijCoreFile.exists()) { ideaArtifactsResolver.downloadTo(ideaArtifactsResolver.INTELLIJ_CORE_ZIP, locallyDownloadedIntellijCoreFile) } copy { from(zipTree(locallyDownloadedIntellijCoreFile)) setIncludes(setOf("intellij-core.jar")) includeEmptyDirs = false into(libDir) } } } val downloadIdeaDistributionZipAndExtractSelectedJars by tasks.registering { dependsOn(deleteLibrariesFromLibFolder) val ideaDownloadDir = file("$downloadDir/idea-$ideaVersion") val locallyDownloadedIdeaZipFile by extra { file("$ideaDownloadDir/ideaIC.zip") } val chosenJars by extra { setOf(//"openapi", //"platform-util-ui", "util", "idea", //"trove4j", "platform-api", "platform-impl") } doLast { if(!locallyDownloadedIdeaZipFile.exists()) { ideaArtifactsResolver.downloadTo(ideaArtifactsResolver.IDEA_IC_ZIP, locallyDownloadedIdeaZipFile) } copy { from(zipTree(locallyDownloadedIdeaZipFile)) setIncludes(chosenJars.map { "lib/$it.jar" }.toSet()) includeEmptyDirs = false into(libDir) // flatten the files eachFile { this.relativePath = RelativePath(true, this.name) } } } } val extractSelectedFilesFromIdeaJars by tasks.registering { dependsOn(downloadIdeaDistributionZipAndExtractSelectedJars) val packages by extra { /*new PackageListFromManifest("META-INF/MANIFEST.MF"),*/ PackageListFromSimpleFile(file("referencedPackages.txt").path).pathsToInclude } val extractDir by extra { file("$downloadDir/dependencies") } doLast { val chosenJars: Set by downloadIdeaDistributionZipAndExtractSelectedJars.get().extra for (library in chosenJars) { copy { from(zipTree("$libDir/$library.jar")) setIncludes(packages) includeEmptyDirs = false into(extractDir) } file("$libDir/$library.jar").delete() } } } val createIdeDependenciesJar by tasks.registering(Jar::class) { dependsOn(extractSelectedFilesFromIdeaJars) val extractDir: File by extractSelectedFilesFromIdeaJars.get().extra from(extractDir) destinationDirectory.set(libDir) archiveFileName.set("ide-dependencies.jar") manifest { attributes(mapOf("Built-By" to "JetBrains", "Implementation-Vendor" to "JetBrains", "Implementation-Version" to "1.0", "Implementation-Title" to "ide-dependencies")) } doLast { extractDir.deleteRecursively() } } val downloadKotlinxLibraries by tasks.registering(Copy::class) { from(kotlinxLibraries) into(libDir) rename("(kotlinx-coroutines-\\w+)-.*", "$1.jar") } val downloadIdeaAndKotlinCompilerSources by tasks.registering { val locallyDownloadedKotlinCompilerSourcesFile by extra { file("$downloadDir/kotlin-compiler-sources.jar") } val locallyDownloadedIdeaSourcesFile by extra { file("$downloadDir/idea-sdk-sources.jar") } doLast { if(!locallyDownloadedKotlinCompilerSourcesFile.exists()) { //TODO can we get the sources from somewhere? //tcArtifactsResolver.downloadTo(tcArtifactsResolver.KOTLIN_COMPILER_SOURCES_JAR, locallyDownloadedKotlinCompilerSourcesFile) } if(!locallyDownloadedIdeaSourcesFile.exists()) { ideaArtifactsResolver.downloadTo(ideaArtifactsResolver.IDEA_IC_SOURCES_JAR, locallyDownloadedIdeaSourcesFile) } } } val repackageIdeaAndKotlinCompilerSources by tasks.registering(Zip::class) { dependsOn(downloadIdeaAndKotlinCompilerSources) val locallyDownloadedKotlinCompilerSourcesFile: File by downloadIdeaAndKotlinCompilerSources.get().extra val locallyDownloadedIdeaSourcesFile: File by downloadIdeaAndKotlinCompilerSources.get().extra from(zipTree(locallyDownloadedKotlinCompilerSourcesFile)) from(zipTree(locallyDownloadedIdeaSourcesFile)) destinationDirectory.set(libDir) archiveFileName.set("kotlin-compiler-sources.jar") } val downloadBundled by tasks.registering { libDir.listFiles()?.filter { it.isFile }?.forEach { it.deleteRecursively() } if (localTCArtifacts) { dependsOn(extractPackagesFromPlugin, extractPackagesFromKTCompiler, downloadIntellijCoreAndExtractSelectedJars, createIdeDependenciesJar, downloadKotlinxLibraries) } else { dependsOn(extractPackagesFromPlugin, extractPackagesFromKTCompiler, downloadIntellijCoreAndExtractSelectedJars, createIdeDependenciesJar, downloadKotlinxLibraries) } if (!ignoreSources) { dependsOn(repackageIdeaAndKotlinCompilerSources) } } val getBundled by tasks.registering { dependsOn(downloadTestData, downloadTestFrameworkDependencies, downloadBundled) } ================================================ FILE: kotlin-bundled-compiler/build.properties ================================================ ############################################################################### # Copyright 2000-2014 JetBrains s.r.o. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### source.. = src/ output.. = bin/ bin.includes = META-INF/,\ .,\ lib/kotlin-compiler.jar,\ lib/kotlin-stdlib.jar,\ lib/kotlin-reflect.jar,\ lib/kotlin-stdlib-sources.jar,\ lib/kotlin-script-runtime.jar,\ lib/allopen-compiler-plugin.jar,\ lib/kotlin-scripting-compiler.jar,\ lib/sam-with-receiver-compiler-plugin.jar,\ lib/noarg-compiler-plugin.jar,\ lib/annotations-13.0.jar,\ lib/kotlinx-coroutines-core.jar,\ lib/kotlinx-coroutines-jdk8.jar,\ lib/ide-dependencies.jar,\ lib/kotlin-scripting-common.jar,\ lib/kotlin-scripting-jvm.jar,\ lib/kotlin-scripting-compiler-impl.jar,\ lib/kotlin-plugin-parts.jar,\ lib/kotlin-formatter.jar,\ lib/kotlin-common.jar,\ lib/kotlin-idea.jar,\ lib/kotlin-core.jar,\ lib/kotlin-j2k-old.jar,\ lib/kotlin-j2k-new.jar,\ lib/kotlin-j2k-idea.jar,\ lib/kotlin-j2k-services.jar,\ lib/kotlin-frontend-independent.jar,\ lib/ide-common.jar src.includes = lib/ bin.excludes = lib/kotlin-compiler-sources.jar,\ lib/downloads/ src.excludes = lib/downloads/,\ lib/intellij-core.jar ================================================ FILE: kotlin-bundled-compiler/buildSrc/build.gradle ================================================ apply plugin: 'groovy' repositories { jcenter() mavenCentral() maven { url 'https://jitpack.io' } } dependencies { implementation 'org.jetbrains.teamcity:teamcity-rest-client:1.5.0' testImplementation('org.spockframework:spock-core:2.2-groovy-3.0') { exclude module : 'groovy-all' } testImplementation 'com.github.stefanbirkner:system-rules:1.19.0' testImplementation 'org.apache.commons:commons-lang3:3.8.1' } test.enabled = false // otherwise integration tests will run always before the actual build ================================================ FILE: kotlin-bundled-compiler/buildSrc/src/main/groovy/com/intellij/buildsupport/dependencies/PackageList.groovy ================================================ package com.intellij.buildsupport.dependencies abstract class PackageList { List getPathsToInclude() { List tempList = [] packageNames.forEach { if(it.startsWith("custom:")) { tempList.add(it.replace("custom:", "")) } else { tempList.add(it.replace('.', '/') + '/*.class') } } return tempList } protected abstract List getPackageNames() } ================================================ FILE: kotlin-bundled-compiler/buildSrc/src/main/groovy/com/intellij/buildsupport/dependencies/PackageListFromManifest.groovy ================================================ package com.intellij.buildsupport.dependencies import groovy.transform.TupleConstructor import java.util.jar.Manifest @TupleConstructor class PackageListFromManifest extends PackageList { String path @Override protected List getPackageNames() { new Manifest(new FileInputStream(path)).mainAttributes .getValue("Export-Package") .split(',') *.takeWhile { it != ';' } as List } } ================================================ FILE: kotlin-bundled-compiler/buildSrc/src/main/groovy/com/intellij/buildsupport/dependencies/PackageListFromSimpleFile.groovy ================================================ package com.intellij.buildsupport.dependencies import groovy.transform.TupleConstructor import java.util.jar.Manifest @TupleConstructor class PackageListFromSimpleFile extends PackageList { String path @Override protected List getPackageNames() { new FileInputStream(path).readLines() *.trim() .findAll { !it.empty } .findAll { it.take(1) != '#' } } } ================================================ FILE: kotlin-bundled-compiler/buildSrc/src/main/groovy/com/intellij/buildsupport/resolve/http/HttpArtifact.groovy ================================================ package com.intellij.buildsupport.resolve.http import groovy.transform.EqualsAndHashCode import groovy.transform.ToString import groovy.transform.TupleConstructor @TupleConstructor(includeFields = true) @EqualsAndHashCode @ToString class HttpArtifact { // relative to HTTP base URL final String filePath // cannot contain any regex patterns } ================================================ FILE: kotlin-bundled-compiler/buildSrc/src/main/groovy/com/intellij/buildsupport/resolve/http/HttpArtifactsResolver.groovy ================================================ package com.intellij.buildsupport.resolve.http import groovy.transform.TupleConstructor @TupleConstructor(includeFields = true) class HttpArtifactsResolver { // FIELDS ========================================================================================================= protected final String httpBaseUrl static Map proxyProps = new HashMap<>() // PUBLIC API ===================================================================================================== final void downloadTo(HttpArtifact httpArtifact, File outputFile) { println "Downloading artifact: $httpArtifact.filePath" downloadFileFromUrlInto "$httpBaseUrl/$httpArtifact.filePath", outputFile } // PRIVATE API ==================================================================================================== private void downloadFileFromUrlInto(String fileURL, File destinationFile) { destinationFile.parentFile.mkdirs() def ant = new AntBuilder() if (!proxyProps.isEmpty() && proxyProps['https.proxyHost'] != null) { if (proxyProps.get("https.proxyUser") == null) { ant.setproxy(proxyHost: proxyProps['https.proxyHost'], proxyPort: proxyProps['https.proxyPort']) } else { ant.setproxy(proxyHost: proxyProps['https.proxyHost'], proxyPort: proxyProps['https.proxyPort'], proxyUser: proxyProps['https.proxyUser'], proxyPassword: proxyProps['https.proxyPassword']) } } ant.get(src: fileURL, dest: destinationFile, usetimestamp: true) } } ================================================ FILE: kotlin-bundled-compiler/buildSrc/src/main/groovy/com/intellij/buildsupport/resolve/http/idea/IntellijIdeaArtifactsResolver.groovy ================================================ package com.intellij.buildsupport.resolve.http.idea import com.intellij.buildsupport.resolve.http.HttpArtifact import com.intellij.buildsupport.resolve.http.HttpArtifactsResolver import groovy.transform.CompileStatic @CompileStatic class IntellijIdeaArtifactsResolver extends HttpArtifactsResolver { final String ideaVersion IntellijIdeaArtifactsResolver(String httpBaseUrl, String ideaVersion) { super(httpBaseUrl) this.ideaVersion = ideaVersion } public final HttpArtifact INTELLIJ_CORE_ZIP = new HttpArtifact("intellij-core/$ideaVersion/intellij-core-${ideaVersion}.zip",) public final HttpArtifact IDEA_IC_ZIP = new HttpArtifact("ideaIC/$ideaVersion/ideaIC-${ideaVersion}.zip",) public final HttpArtifact IDEA_IC_SOURCES_JAR = new HttpArtifact("ideaIC/$ideaVersion/ideaIC-$ideaVersion-sources.jar",) } ================================================ FILE: kotlin-bundled-compiler/buildSrc/src/main/groovy/com/intellij/buildsupport/resolve/tc/TCArtifact.groovy ================================================ package com.intellij.buildsupport.resolve.tc import groovy.transform.EqualsAndHashCode import groovy.transform.ToString import groovy.transform.TupleConstructor @TupleConstructor(includeFields = true) @EqualsAndHashCode @ToString class TCArtifact { // relative to TeamCity base URL final String fileParentPathRegex // might contain '*' pattern final String fileNameRegex // might contain '*' pattern } ================================================ FILE: kotlin-bundled-compiler/buildSrc/src/main/groovy/com/intellij/buildsupport/resolve/tc/TCArtifactsResolver.groovy ================================================ package com.intellij.buildsupport.resolve.tc import groovy.transform.CompileStatic import groovy.transform.TupleConstructor import org.jetbrains.teamcity.rest.Build import org.jetbrains.teamcity.rest.BuildArtifact import org.jetbrains.teamcity.rest.BuildConfigurationId import org.jetbrains.teamcity.rest.BuildId import org.jetbrains.teamcity.rest.BuildLocator import org.jetbrains.teamcity.rest.TeamCityConversationException import org.jetbrains.teamcity.rest.TeamCityInstanceFactory import org.jetbrains.teamcity.rest.TeamCityQueryException @TupleConstructor(includeFields = true, excludes = ['resolvedArtifactMap', 'untilDate']) @CompileStatic abstract class TCArtifactsResolver { // FIELDS ========================================================================================================= protected final String teamcityBaseUrl protected final boolean lastSuccessfulBuild protected final String tcBuildId protected final String tcBuildBranch // for testing purposes only protected Date untilDate = null private Map resolvedArtifactMap = null // ABSTRACT METHODS TO IMPLEMENT ================================================================================== abstract List getRequiredArtifacts() abstract String tcBuildTypeId() // PUBLIC API ===================================================================================================== final void downloadTo(TCArtifact tcArtifact, File outputFile) { if (resolvedArtifactMap == null) { resolvedArtifactMap = lastSuccessfulBuild ? resolveFromLastSuccessfulBuild() : resolveFromBuildId() } BuildArtifact resolvedTCArtifact = resolvedArtifactMap.get(tcArtifact) println "Downloading artifact: $resolvedTCArtifact.fullName" resolvedTCArtifact.download(outputFile) } // PRIVATE API ==================================================================================================== private Map resolveFromBuildId() { Build tcBuild = TeamCityInstanceFactory.guestAuth(teamcityBaseUrl) .build(new BuildId(tcBuildId)) println "Resolving TC build: $tcBuild" return resolveRequiredArtifacts(tcBuild) } private Map resolveFromLastSuccessfulBuild() { BuildLocator builds = TeamCityInstanceFactory.guestAuth(teamcityBaseUrl) .builds() .fromConfiguration(new BuildConfigurationId(tcBuildTypeId())) .includeFailed() if (!tcBuildBranch.trim().isEmpty()) builds.withBranch(tcBuildBranch.trim()) if (untilDate != null) builds.untilDate(untilDate) for (Build tcBuild in iterable(builds.all())) { println "Resolving TC build: $tcBuild" Map resolvedArtifacts = resolveRequiredArtifacts(tcBuild) if (resolvedArtifacts.isEmpty()) continue else return resolvedArtifacts } } private Map resolveRequiredArtifacts(Build tcBuild) { Map resolvedArtifactMap = [:] as HashMap for (TCArtifact requiredTcArtifact in getRequiredArtifacts()) { BuildArtifact resolvedTcArtifact // search the build and dependencies of the build for the artifact (in case of an aggregate build) for (build in [tcBuild] + tcBuild.snapshotDependencies) { try { resolvedTcArtifact = build.findArtifact(requiredTcArtifact.fileNameRegex, requiredTcArtifact.fileParentPathRegex,true) break } catch (TeamCityConversationException ignored) {} catch (TeamCityQueryException ignored) {} } // in the case the latest build does not contain any artifacts, we continue searching the previous build if(resolvedTcArtifact == null) return Collections.EMPTY_MAP resolvedArtifactMap.put requiredTcArtifact, resolvedTcArtifact } return resolvedArtifactMap } private static Iterable iterable(kotlin.sequences.Sequence sequence) { return sequence.iterator() as Iterable } } ================================================ FILE: kotlin-bundled-compiler/buildSrc/src/main/groovy/com/intellij/buildsupport/resolve/tc/kotlin/CommonIDEArtifactsResolver.groovy ================================================ package com.intellij.buildsupport.resolve.tc.kotlin import com.intellij.buildsupport.resolve.tc.TCArtifact import com.intellij.buildsupport.resolve.tc.TCArtifactsResolver import groovy.transform.CompileStatic @CompileStatic class CommonIDEArtifactsResolver extends TCArtifactsResolver { final String kotlinCompilerVersion CommonIDEArtifactsResolver( String teamcityBaseUrl, boolean lastSuccessfulBuild, String tcBuildId, String kotlinCompilerVersion ) { super(teamcityBaseUrl, lastSuccessfulBuild, tcBuildId, kotlinCompilerVersion) this.kotlinCompilerVersion = kotlinCompilerVersion } public final TCArtifact KOTLIN_FORMATTER_JAR = new TCArtifact('internal', 'kotlin-formatter.jar') public final TCArtifact KOTLIN_IDE_COMMON_JAR = new TCArtifact('internal', 'kotlin-ide-common.jar') @Override List getRequiredArtifacts() { return [ KOTLIN_IDE_COMMON_JAR, KOTLIN_FORMATTER_JAR ] } @Override String tcBuildTypeId() { String kotlinCompilerVersionInBuildId = kotlinCompilerVersion.replace('.', '') // '1.3.0' => '130' .replace('-', '') // '1.3-M2' => '13M2' return "Kotlin_${kotlinCompilerVersionInBuildId}_CompilerAllPlugins" } } ================================================ FILE: kotlin-bundled-compiler/buildSrc/src/main/groovy/com/intellij/buildsupport/resolve/tc/kotlin/KotlinCompilerTCArtifactsResolver.groovy ================================================ package com.intellij.buildsupport.resolve.tc.kotlin import com.intellij.buildsupport.resolve.tc.TCArtifact import com.intellij.buildsupport.resolve.tc.TCArtifactsResolver import groovy.transform.CompileStatic @CompileStatic class KotlinCompilerTCArtifactsResolver extends TCArtifactsResolver { final String kotlinIdeaCompatibleVersionMinor final String kotlinCompilerVersion KotlinCompilerTCArtifactsResolver(String teamcityBaseUrl, boolean lastSuccessfulBuild, String tcBuildId, String kotlinCompilerVersion, String kotlinIdeaCompatibleVersionMinor) { super(teamcityBaseUrl, lastSuccessfulBuild, tcBuildId, kotlinCompilerVersion) this.kotlinCompilerVersion = kotlinCompilerVersion this.kotlinIdeaCompatibleVersionMinor = kotlinIdeaCompatibleVersionMinor } public final TCArtifact KOTLIN_PLUGIN_ZIP = new TCArtifact('', "kotlin-plugin-*-IJ${kotlinIdeaCompatibleVersionMinor}*.zip") public final TCArtifact KOTLIN_TEST_DATA_ZIP = new TCArtifact('internal', 'kotlin-test-data.zip') public final TCArtifact KOTLIN_COMPILER_SOURCES_JAR = new TCArtifact('maven/org/jetbrains/kotlin/kotlin-compiler', 'kotlin-compiler-*-sources.jar') @Override List getRequiredArtifacts() { return [KOTLIN_TEST_DATA_ZIP, KOTLIN_PLUGIN_ZIP, KOTLIN_COMPILER_SOURCES_JAR] } @Override String tcBuildTypeId() { String kotlinCompilerVersionInBuildId = kotlinCompilerVersion.replace('.', '') // '1.3.0' => '130' .replace('-', '') // '1.3-M2' => '13M2' return "Kotlin_${kotlinCompilerVersionInBuildId}_Aggregate" } } ================================================ FILE: kotlin-bundled-compiler/buildSrc/src/main/groovy/com/intellij/buildsupport/utils/FileUtils.groovy ================================================ package com.intellij.buildsupport.utils import groovy.transform.CompileStatic @CompileStatic class FileUtils { private FileUtils() {} static void cleanDir(File dir) { dir.deleteDir() dir.mkdirs() } static void cleanDirExceptSubDirName(File dir, String retainSubDirName) { if (dir.exists()) { dir.eachFile { File file -> if (file.isFile()) file.delete() else if (file.isDirectory()) { if (file.name != retainSubDirName) file.deleteDir() } } } dir.mkdirs() new File("$dir/$retainSubDirName").mkdirs() } } ================================================ FILE: kotlin-bundled-compiler/buildSrc/src/test/groovy/com/intellij/buildsupport/tc/kotlin/KotlinCompilerTCArtifactsResolverSpecification.groovy ================================================ package com.intellij.buildsupport.tc.kotlin import com.intellij.buildsupport.resolve.tc.TCArtifactsResolver import com.intellij.buildsupport.resolve.tc.kotlin.KotlinCompilerTCArtifactsResolver import java.text.SimpleDateFormat import org.junit.Rule import org.junit.contrib.java.lang.system.SystemOutRule import spock.lang.Specification import spock.lang.Unroll import static org.apache.commons.lang3.StringUtils.countMatches class KotlinCompilerTCArtifactsResolverSpecification extends Specification { private static final String TC_BASE_URL = 'https://teamcity.jetbrains.com' @Rule public final SystemOutRule systemOut = new SystemOutRule().enableLog() @Unroll def "should resolve TC artifacts by buildId for version #releaseDescribeVersion"() { setup: def tcArtifactResolver = tcArtifactResolverWithBuildId(tcBuildId, kotlinIdeaCompatibleVersionMinor) def temporaryFile = File.createTempFile("kotlin-compiler-$releaseDescribeVersion", '.tmp') expect: tcArtifactResolver.downloadTo tcArtifactResolver.KOTLIN_PLUGIN_ZIP, temporaryFile assert temporaryFile.exists() where: releaseDescribeVersion | tcBuildId | kotlinIdeaCompatibleVersionMinor '1.2.72-release-68' | '1646860' | '2017.3' '1.3-M2-eap-105' | '1572593' | '2017.3' '1.3.0-rc-153' | '1664232' | '2017.3' } @Unroll def "should resolve TC artifacts for latest successful build for version #kotlinCompilerVersion"() { setup: def tcArtifactResolver = tcArtifactResolverWithLatestBuildAndKotlinCompilerVersion(kotlinCompilerVersion, kotlinIdeaCompatibleVersionMinor) def temporaryFile = File.createTempFile("kotlin-compiler-latest-$kotlinCompilerVersion", '.tmp') expect: tcArtifactResolver.downloadTo tcArtifactResolver.KOTLIN_PLUGIN_ZIP, temporaryFile assert temporaryFile.exists() where: kotlinCompilerVersion | kotlinIdeaCompatibleVersionMinor '1.2.70' | '2017.3' '1.3-M1' | '2017.3' '1.3-M2' | '2017.3' '1.3.0' | '2017.3' } @Unroll def "should resolve TC artifacts for latest successful build without TC artifacts for version #kotlinCompilerVersion"() { setup: def tcArtifactResolver = tcArtifactResolverWithLatestBuildAndKotlinCompilerVersion(kotlinCompilerVersion, kotlinIdeaCompatibleVersionMinor, untilDate) def temporaryFile = File.createTempFile("kotlin-compiler-latest-$kotlinCompilerVersion", '.tmp') expect: tcArtifactResolver.downloadTo tcArtifactResolver.KOTLIN_PLUGIN_ZIP, temporaryFile assert temporaryFile.exists() assert countMatches(systemOut.log, 'Resolving TC build') == expectednumberOfSearchedTcBuilds where: untilDate | kotlinCompilerVersion | kotlinIdeaCompatibleVersionMinor || expectednumberOfSearchedTcBuilds '2018-08-16' | '1.2.60' | '2017.3' || 4 '2018-09-10' | '1.2.70' | '2017.3' || 5 '2018-08-24' | '1.3-M2' | '2017.3' || 4 '2018-10-03' | '1.3.0' | '2017.3' || 11 } private static TCArtifactsResolver tcArtifactResolverWithBuildId(String tcBuildId, String kotlinIdeaCompatibleVersionMinor) { return new KotlinCompilerTCArtifactsResolver(TC_BASE_URL, false, // not searching for last successful build tcBuildId, '', // Kotlin compiler version determined automatically kotlinIdeaCompatibleVersionMinor) } private static TCArtifactsResolver tcArtifactResolverWithLatestBuildAndKotlinCompilerVersion(String kotlinCompilerVersion, String kotlinIdeaCompatibleVersionMinor) { return tcArtifactResolverWithLatestBuildAndKotlinCompilerVersion(kotlinCompilerVersion, kotlinIdeaCompatibleVersionMinor, null) } private static TCArtifactsResolver tcArtifactResolverWithLatestBuildAndKotlinCompilerVersion(String kotlinCompilerVersion, String kotlinIdeaCompatibleVersionMinor, String untilDate) { TCArtifactsResolver tcArtifactsResolver = new KotlinCompilerTCArtifactsResolver(TC_BASE_URL, true, // searching for last successful build '', // buildId not used kotlinCompilerVersion, kotlinIdeaCompatibleVersionMinor) if (untilDate != null) tcArtifactsResolver.untilDate = new SimpleDateFormat("yyyy-MM-dd").parse(untilDate) return tcArtifactsResolver } } ================================================ FILE: kotlin-bundled-compiler/gradle/wrapper/gradle-wrapper.properties ================================================ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists ================================================ FILE: kotlin-bundled-compiler/gradlew ================================================ #!/usr/bin/env sh # # Copyright 2015 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. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################## ## ## Gradle start up script for UN*X ## ############################################################################## # Attempt to set APP_HOME # Resolve links: $0 may be a link PRG="$0" # Need this for relative symlinks. while [ -h "$PRG" ] ; do ls=`ls -ld "$PRG"` link=`expr "$ls" : '.*-> \(.*\)$'` if expr "$link" : '/.*' > /dev/null; then PRG="$link" else PRG=`dirname "$PRG"`"/$link" fi done SAVED="`pwd`" cd "`dirname \"$PRG\"`/" >/dev/null APP_HOME="`pwd -P`" cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" warn () { echo "$*" } die () { echo echo "$*" echo exit 1 } # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false case "`uname`" in CYGWIN* ) cygwin=true ;; Darwin* ) darwin=true ;; MINGW* ) msys=true ;; NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD="$JAVA_HOME/jre/sh/java" else JAVACMD="$JAVA_HOME/bin/java" fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else JAVACMD="java" which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi # Increase the maximum file descriptors if we can. if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then MAX_FD="$MAX_FD_LIMIT" fi ulimit -n $MAX_FD if [ $? -ne 0 ] ; then warn "Could not set maximum file descriptor limit: $MAX_FD" fi else warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" fi fi # For Darwin, add options to specify how the application appears in the dock if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi # For Cygwin, switch paths to Windows format before running java if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` SEP="" for dir in $ROOTDIRSRAW ; do ROOTDIRS="$ROOTDIRS$SEP$dir" SEP="|" done OURCYGPATTERN="(^($ROOTDIRS))" # Add a user-defined pattern to the cygpath arguments if [ "$GRADLE_CYGPATTERN" != "" ] ; then OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" fi # Now convert the arguments - kludge to limit ourselves to /bin/sh i=0 for arg in "$@" ; do CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` else eval `echo args$i`="\"$arg\"" fi i=$((i+1)) done case $i in (0) set -- ;; (1) set -- "$args0" ;; (2) set -- "$args0" "$args1" ;; (3) set -- "$args0" "$args1" "$args2" ;; (4) set -- "$args0" "$args1" "$args2" "$args3" ;; (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi # Escape application args save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } APP_ARGS=$(save "$@") # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then cd "$(dirname "$0")" fi exec "$JAVACMD" "$@" ================================================ FILE: kotlin-bundled-compiler/gradlew.bat ================================================ @rem @rem Copyright 2015 the original author or authors. @rem @rem Licensed under the Apache License, Version 2.0 (the "License"); @rem you may not use this file except in compliance with the License. @rem You may obtain a copy of the License at @rem @rem https://www.apache.org/licenses/LICENSE-2.0 @rem @rem Unless required by applicable law or agreed to in writing, software @rem distributed under the License is distributed on an "AS IS" BASIS, @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @rem @rem ########################################################################## @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if "%ERRORLEVEL%" == "0" goto init echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto init echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :init @rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args :win9xME_args @rem Slurp the command line arguments. set CMD_LINE_ARGS= set _SKIP=2 :win9xME_args_slurp if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% :end @rem End local scope for the variables with windows NT shell if "%ERRORLEVEL%"=="0" goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 exit /b 1 :mainEnd if "%OS%"=="Windows_NT" endlocal :omega ================================================ FILE: kotlin-bundled-compiler/pom.xml ================================================ 4.0.0 ../pom.xml kotlin.eclipse kotlin.eclipse.plugin 0.8.24-SNAPSHOT org.jetbrains.kotlin.bundled-compiler eclipse-plugin src org.jetbrains.kotlin kotlin-maven-plugin ${kotlin.version} 17 compile process-sources compile org.apache.maven.plugins maven-compiler-plugin 3.10.1 17 with-gradle org.codehaus.mojo exec-maven-plugin 3.0.0 gradle-clean clean exec ${project.basedir}/gradlew clean gradle-getBundled validate exec ${project.basedir}/gradlew getBundled ================================================ FILE: kotlin-bundled-compiler/referencedPackages.txt ================================================ # List of packages that are referenced from other dependencies and should be included in plugin to avoid classpath issues com.intellij.psi.codeStyle com.intellij.psi.formatter com.intellij.openapi.components com.intellij.openapi.options com.intellij.application.options com.intellij.application.options.codeStyle.properties com.intellij.formatting com.intellij.formatting.engine com.intellij.util.containers gnu.trove com.intellij.openapi.util com.intellij.openapi.util.text com.intellij.psi.codeStyle.arrangement com.intellij.configurationStore com.intellij.openapi.progress com.intellij.ui com.intellij.util.text custom:com/intellij/CodeStyleBundle.class custom:com/intellij/DynamicBundle.class custom:com/intellij/AbstractBundle.class custom:messages/CodeStyleBundle.* it.unimi.dsi.fastutil.objects ================================================ FILE: kotlin-bundled-compiler/src/com/intellij/codeInsight/CodeInsightBundle.java ================================================ package com.intellij.codeInsight; public class CodeInsightBundle { public static String message(String key, Object... params) { return key; } } ================================================ FILE: kotlin-bundled-compiler/src/com/intellij/codeInsight/KotlinNullableNotNullManager.kt ================================================ /******************************************************************************* * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package com.intellij.codeInsight import com.intellij.openapi.project.Project import com.intellij.psi.PsiAnnotation import com.intellij.psi.PsiElement import com.intellij.psi.PsiModifierListOwner import org.jetbrains.annotations.Nullable // Dummy implementation. Will be changed to something more useful, when KE-277 is fixed. class KotlinNullableNotNullManager(project: Project) : NullableNotNullManager(project) { private val _nullables = mutableListOf() private val _notNulls = mutableListOf() override fun getNullables(): List = _nullables override fun setInstrumentedNotNulls(names: MutableList) {} override fun getInstrumentedNotNulls(): List = emptyList() // override fun isJsr305Default(annotation: PsiAnnotation, placeTargetTypes: Array): NullabilityAnnotationInfo? = null override fun setNullables(vararg annotations: String) { _nullables.clear() _nullables.addAll(annotations) } override fun getNotNulls(): List = _notNulls override fun setDefaultNotNull(defaultNotNull: String) { } override fun getDefaultNullable(): String = "Nullable" override fun getDefaultNotNull(): String { return "NotNullable" } override fun getDefaultNullables(): MutableList { return mutableListOf(defaultNullable) } override fun getDefaultNotNulls(): MutableList { return mutableListOf(defaultNotNull) } override fun getAllDefaultAnnotations(): MutableList { return (defaultNullables + defaultNotNulls).toMutableList() } override fun setNotNulls(vararg annotations: String) { _notNulls.clear() _notNulls.addAll(annotations) } // For now we get unresolved psi elements and as a result annotations qualified names are short init { setNotNulls("NotNull") setNullables("Nullable") } override fun setDefaultNullable(defaultNullable: String) { } override fun hasHardcodedContracts(element: PsiElement): Boolean = false override fun isNotNull(owner: PsiModifierListOwner, checkBases: Boolean): Boolean { val notNullAnnotations = notNulls.toSet() return owner.modifierList?.annotations?.any { annotation -> annotation.qualifiedName in notNullAnnotations } ?: false } @Nullable override fun getNullityDefault( container: PsiModifierListOwner, placeTargetTypes: Array, context: PsiElement, superPackage: Boolean ): NullabilityAnnotationInfo? { return null } override fun isNullable(owner: PsiModifierListOwner, checkBases: Boolean) = !isNotNull(owner, checkBases) } ================================================ FILE: kotlin-bundled-compiler/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java ================================================ package com.intellij.codeInsight.actions; public class ReformatCodeProcessor { public static final String COMMAND_NAME = "dummy"; public static String getCommandName() { return "Reformat Code"; } } ================================================ FILE: kotlin-bundled-compiler/src/com/intellij/codeInsight/generation/GenerateEqualsHelper.java ================================================ package com.intellij.codeInsight.generation; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiClassType; import com.intellij.psi.PsiManager; import com.intellij.psi.PsiSubstitutor; import com.intellij.psi.PsiType; import com.intellij.psi.PsiTypeParameter; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.MethodSignature; import com.intellij.psi.util.MethodSignatureUtil; // Temp workaround for bad j2k classes politics public class GenerateEqualsHelper { public static MethodSignature getEqualsSignature(Project project, GlobalSearchScope scope) { final PsiClassType javaLangObject = PsiType.getJavaLangObject(PsiManager.getInstance(project), scope); return MethodSignatureUtil.createMethodSignature( "equals", new PsiType[]{javaLangObject}, PsiTypeParameter.EMPTY_ARRAY, PsiSubstitutor.EMPTY); } } ================================================ FILE: kotlin-bundled-compiler/src/com/intellij/formatting/KotlinLanguageCodeStyleSettingsProvider.kt ================================================ package com.intellij.formatting import org.jetbrains.kotlin.idea.KotlinLanguage import com.intellij.application.options.IndentOptionsEditor import com.intellij.lang.Language import com.intellij.psi.codeStyle.CodeStyleSettingsCustomizable import com.intellij.psi.codeStyle.CommonCodeStyleSettings import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider import org.jetbrains.kotlin.idea.formatter.KotlinCommonCodeStyleSettings class KotlinLanguageCodeStyleSettingsProvider : LanguageCodeStyleSettingsProvider() { override fun getLanguage(): Language = KotlinLanguage.INSTANCE override fun getCodeSample(settingsType: SettingsType): String = "" override fun getLanguageName(): String = KotlinLanguage.NAME override fun customizeSettings(consumer:CodeStyleSettingsCustomizable, settingsType:SettingsType) { } override fun getIndentOptionsEditor(): IndentOptionsEditor? = null override fun getDefaultCommonSettings(): CommonCodeStyleSettings { val commonCodeStyleSettings = KotlinCommonCodeStyleSettings() commonCodeStyleSettings.initIndentOptions() return commonCodeStyleSettings } } ================================================ FILE: kotlin-bundled-compiler/src/com/intellij/formatting/KotlinSettingsProvider.kt ================================================ package com.intellij.formatting import com.intellij.lang.Language import com.intellij.openapi.options.Configurable import com.intellij.psi.codeStyle.CodeStyleSettings import com.intellij.psi.codeStyle.CodeStyleSettingsProvider import com.intellij.psi.codeStyle.CustomCodeStyleSettings import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings class KotlinSettingsProvider : CodeStyleSettingsProvider() { override fun getConfigurableDisplayName(): String = KotlinLanguage.NAME override fun getLanguage(): Language = KotlinLanguage.INSTANCE override fun createCustomSettings(settings: CodeStyleSettings): CustomCodeStyleSettings { return KotlinCodeStyleSettings(settings).apply { this.ALLOW_TRAILING_COMMA = true this.ALLOW_TRAILING_COMMA_ON_CALL_SITE = true } } override fun createSettingsPage(settings: CodeStyleSettings, originalSettings: CodeStyleSettings): Configurable { throw UnsupportedOperationException() } } ================================================ FILE: kotlin-bundled-compiler/src/com/intellij/openapi/editor/Editor.java ================================================ package com.intellij.openapi.editor; public class Editor { } ================================================ FILE: kotlin-bundled-compiler/src/com/intellij/openapi/extensions/ExtensionException.kt ================================================ package com.intellij.openapi.extensions class ExtensionException(val extensionClass: Class<*>) : RuntimeException(extensionClass.getCanonicalName()) ================================================ FILE: kotlin-bundled-compiler/src/com/intellij/openapi/fileTypes/StdFileTypes.java ================================================ package com.intellij.openapi.fileTypes; public class StdFileTypes { public static final LanguageFileType JAVA = null; } ================================================ FILE: kotlin-bundled-compiler/src/com/intellij/openapi/util/text/StringUtil.java ================================================ // Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.openapi.util.text; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProcessCanceledException; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.util.*; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.text.*; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.text.MutableAttributeSet; import javax.swing.text.html.HTML; import javax.swing.text.html.HTMLEditorKit; import javax.swing.text.html.parser.ParserDelegator; import java.beans.Introspector; import java.io.IOException; import java.io.Reader; import java.io.StringReader; import java.util.*; import java.util.StringTokenizer; import java.util.regex.Matcher; import java.util.regex.Pattern; //TeamCity inherits StringUtil: do not add private constructors!!! @SuppressWarnings("MethodOverridesStaticMethodOfSuperclass") public class StringUtil extends StringUtilRt { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.util.text.StringUtil"); @SuppressWarnings("SpellCheckingInspection") private static final String VOWELS = "aeiouy"; private static final Pattern EOL_SPLIT_KEEP_SEPARATORS = Pattern.compile("(?<=(\r\n|\n))|(?<=\r)(?=[^\n])"); private static final Pattern EOL_SPLIT_PATTERN = Pattern.compile(" *(\r|\n|\r\n)+ *"); private static final Pattern EOL_SPLIT_PATTERN_WITH_EMPTY = Pattern.compile(" *(\r|\n|\r\n) *"); private static final Pattern EOL_SPLIT_DONT_TRIM_PATTERN = Pattern.compile("(\r|\n|\r\n)+"); @NotNull public static MergingCharSequence replaceSubSequence(@NotNull CharSequence charSeq, int start, int end, @NotNull CharSequence replacement) { return new MergingCharSequence( new MergingCharSequence(charSeq.subSequence(0, start), replacement), charSeq.subSequence(end, charSeq.length())); } @Contract(value = "null -> null; !null->!null", pure = true) public static String internEmptyString(String s) { return s == null ? null : (s.isEmpty() ? "" : s); } private static class MyHtml2Text extends HTMLEditorKit.ParserCallback { @NotNull private final StringBuilder myBuffer = new StringBuilder(); private final boolean myIsSkipStyleTag; private boolean myIsStyleTagOpened; private MyHtml2Text(boolean isSkipStyleTag) { myIsSkipStyleTag = isSkipStyleTag; } public void parse(@NotNull Reader in) throws IOException { myBuffer.setLength(0); new ParserDelegator().parse(in, this, Boolean.TRUE); } @Override public void handleText(@NotNull char[] text, int pos) { if (!myIsStyleTagOpened) { myBuffer.append(text); } } @Override public void handleStartTag(@NotNull HTML.Tag tag, MutableAttributeSet set, int i) { if (myIsSkipStyleTag && "style".equals(tag.toString())) { myIsStyleTagOpened = true; } handleTag(tag); } @Override public void handleEndTag(@NotNull HTML.Tag tag, int pos) { if (myIsSkipStyleTag && "style".equals(tag.toString())) { myIsStyleTagOpened = false; } } @Override public void handleSimpleTag(HTML.Tag tag, MutableAttributeSet set, int i) { handleTag(tag); } private void handleTag(@NotNull HTML.Tag tag) { if (tag.breaksFlow() && myBuffer.length() > 0) { myBuffer.append(SystemProperties.getLineSeparator()); } } @NotNull public String getText() { return myBuffer.toString(); } } private static final MyHtml2Text html2TextParser = new MyHtml2Text(false); public static final NotNullFunction QUOTER = new NotNullFunction() { @Override @NotNull public String fun(String s) { return "\"" + s + "\""; } }; public static final NotNullFunction SINGLE_QUOTER = new NotNullFunction() { @Override @NotNull public String fun(String s) { return "'" + s + "'"; } }; @NotNull @Contract(pure = true) public static List getWordsInStringLongestFirst(@NotNull String find) { List words = getWordsIn(find); // hope long words are rare Collections.sort(words, new Comparator() { @Override public int compare(@NotNull final String o1, @NotNull final String o2) { return o2.length() - o1.length(); } }); return words; } @NotNull @Contract(pure = true) public static String escapePattern(@NotNull final String text) { return replace(replace(text, "'", "''"), "{", "'{'"); } @NotNull @Contract(pure = true) public static Function createToStringFunction(@SuppressWarnings("unused") @NotNull Class cls) { return new Function() { @Override public String fun(@NotNull T o) { return o.toString(); } }; } @NotNull public static final Function TRIMMER = new Function() { @Nullable @Override public String fun(@Nullable String s) { return trim(s); } }; // Unlike String.replace(CharSequence,CharSequence) does not allocate intermediate objects on non-match // TODO revise when JDK9 arrives - its String.replace(CharSequence, CharSequence) is more optimized @NotNull @Contract(pure = true) public static String replace(@NotNull String text, @NotNull String oldS, @NotNull String newS) { return replace(text, oldS, newS, false); } @NotNull @Contract(pure = true) public static String replaceIgnoreCase(@NotNull String text, @NotNull String oldS, @NotNull String newS) { return replace(text, oldS, newS, true); } /** * @deprecated Use {@link String#replace(char,char)} instead */ @NotNull @Contract(pure = true) @Deprecated public static String replaceChar(@NotNull String buffer, char oldChar, char newChar) { return buffer.replace(oldChar, newChar); } @Contract(pure = true) public static String replace(@NotNull final String text, @NotNull final String oldS, @NotNull final String newS, final boolean ignoreCase) { if (text.length() < oldS.length()) return text; StringBuilder newText = null; int i = 0; while (i < text.length()) { final int index = ignoreCase? indexOfIgnoreCase(text, oldS, i) : text.indexOf(oldS, i); if (index < 0) { if (i == 0) { return text; } newText.append(text, i, text.length()); break; } else { if (newText == null) { if (text.length() == oldS.length()) { return newS; } newText = new StringBuilder(text.length() - i); } newText.append(text, i, index); newText.append(newS); i = index + oldS.length(); } } return newText != null ? newText.toString() : ""; } @Contract(pure = true) public static int indexOfIgnoreCase(@NotNull String where, @NotNull String what, int fromIndex) { return indexOfIgnoreCase((CharSequence)where, what, fromIndex); } /** * Implementation copied from {@link String#indexOf(String, int)} except character comparisons made case insensitive */ @Contract(pure = true) public static int indexOfIgnoreCase(@NotNull CharSequence where, @NotNull CharSequence what, int fromIndex) { int targetCount = what.length(); int sourceCount = where.length(); if (fromIndex >= sourceCount) { return targetCount == 0 ? sourceCount : -1; } if (fromIndex < 0) { fromIndex = 0; } if (targetCount == 0) { return fromIndex; } char first = what.charAt(0); int max = sourceCount - targetCount; for (int i = fromIndex; i <= max; i++) { /* Look for first character. */ if (!charsEqualIgnoreCase(where.charAt(i), first)) { //noinspection StatementWithEmptyBody,AssignmentToForLoopParameter while (++i <= max && !charsEqualIgnoreCase(where.charAt(i), first)) ; } /* Found first character, now look at the rest of v2 */ if (i <= max) { int j = i + 1; int end = j + targetCount - 1; //noinspection StatementWithEmptyBody for (int k = 1; j < end && charsEqualIgnoreCase(where.charAt(j), what.charAt(k)); j++, k++) ; if (j == end) { /* Found whole string. */ return i; } } } return -1; } @Contract(pure = true) public static int indexOfIgnoreCase(@NotNull String where, char what, int fromIndex) { int sourceCount = where.length(); for (int i = Math.max(fromIndex, 0); i < sourceCount; i++) { if (charsEqualIgnoreCase(where.charAt(i), what)) { return i; } } return -1; } @Contract(pure = true) public static int lastIndexOfIgnoreCase(@NotNull String where, char what, int fromIndex) { for (int i = Math.min(fromIndex, where.length() - 1); i >= 0; i--) { if (charsEqualIgnoreCase(where.charAt(i), what)) { return i; } } return -1; } @Contract(pure = true) public static boolean containsIgnoreCase(@NotNull String where, @NotNull String what) { return indexOfIgnoreCase(where, what, 0) >= 0; } @Contract(pure = true) public static boolean endsWithIgnoreCase(@NotNull String str, @NotNull String suffix) { return StringUtilRt.endsWithIgnoreCase(str, suffix); } @Contract(pure = true) public static boolean startsWithIgnoreCase(@NotNull String str, @NotNull String prefix) { return StringUtilRt.startsWithIgnoreCase(str, prefix); } @Contract(pure = true) @NotNull public static String stripHtml(@NotNull String html, boolean convertBreaks) { if (convertBreaks) { html = html.replaceAll("
", "\n\n"); } return html.replaceAll("<(.|\n)*?>", ""); } @Contract(value = "null -> null; !null -> !null", pure = true) public static String toLowerCase(@Nullable final String str) { return str == null ? null : str.toLowerCase(); } @NotNull @Contract(pure = true) public static String getPackageName(@NotNull String fqName) { return getPackageName(fqName, '.'); } /** * Given a fqName returns the package name for the type or the containing type. *

*

    *
  • {@code java.lang.String} -> {@code java.lang}
  • *
  • {@code java.util.Map.Entry} -> {@code java.util.Map}
  • *
* * @param fqName a fully qualified type name. Not supposed to contain any type arguments * @param separator the separator to use. Typically '.' * @return the package name of the type or the declarator of the type. The empty string if the given fqName is unqualified */ @NotNull @Contract(pure = true) public static String getPackageName(@NotNull String fqName, char separator) { int lastPointIdx = fqName.lastIndexOf(separator); if (lastPointIdx >= 0) { return fqName.substring(0, lastPointIdx); } return ""; } @Contract(pure = true) public static int getLineBreakCount(@NotNull CharSequence text) { int count = 0; for (int i = 0; i < text.length(); i++) { char c = text.charAt(i); if (c == '\n') { count++; } else if (c == '\r') { if (i + 1 < text.length() && text.charAt(i + 1) == '\n') { //noinspection AssignmentToForLoopParameter i++; } count++; } } return count; } @Contract(pure = true) public static boolean containsLineBreak(@NotNull CharSequence text) { for (int i = 0; i < text.length(); i++) { char c = text.charAt(i); if (isLineBreak(c)) return true; } return false; } @Contract(pure = true) public static boolean isLineBreak(char c) { return c == '\n' || c == '\r'; } @NotNull @Contract(pure = true) public static String escapeLineBreak(@NotNull String text) { StringBuilder buffer = new StringBuilder(text.length()); for (int i = 0; i < text.length(); i++) { char c = text.charAt(i); switch (c) { case '\n': buffer.append("\\n"); break; case '\r': buffer.append("\\r"); break; default: buffer.append(c); } } return buffer.toString(); } @Contract(pure = true) public static boolean endsWithLineBreak(@NotNull CharSequence text) { int len = text.length(); return len > 0 && isLineBreak(text.charAt(len - 1)); } @Contract(pure = true) public static int lineColToOffset(@NotNull CharSequence text, int line, int col) { int curLine = 0; int offset = 0; while (line != curLine) { if (offset == text.length()) return -1; char c = text.charAt(offset); if (c == '\n') { curLine++; } else if (c == '\r') { curLine++; if (offset < text.length() - 1 && text.charAt(offset + 1) == '\n') { offset++; } } offset++; } return offset + col; } @Contract(pure = true) public static int offsetToLineNumber(@NotNull CharSequence text, int offset) { LineColumn lineColumn = offsetToLineColumn(text, offset); return lineColumn != null ? lineColumn.line : -1; } @Contract(pure = true) public static LineColumn offsetToLineColumn(@NotNull CharSequence text, int offset) { int curLine = 0; int curLineStart = 0; int curOffset = 0; while (curOffset < offset) { if (curOffset == text.length()) return null; char c = text.charAt(curOffset); if (c == '\n') { curLine++; curLineStart = curOffset + 1; } else if (c == '\r') { curLine++; if (curOffset < text.length() - 1 && text.charAt(curOffset + 1) == '\n') { curOffset++; } curLineStart = curOffset + 1; } curOffset++; } return LineColumn.of(curLine, offset - curLineStart); } /** * Classic dynamic programming algorithm for string differences. */ @Contract(pure = true) public static int difference(@NotNull String s1, @NotNull String s2) { int[][] a = new int[s1.length()][s2.length()]; for (int i = 0; i < s1.length(); i++) { a[i][0] = i; } for (int j = 0; j < s2.length(); j++) { a[0][j] = j; } for (int i = 1; i < s1.length(); i++) { for (int j = 1; j < s2.length(); j++) { a[i][j] = Math.min(Math.min(a[i - 1][j - 1] + (s1.charAt(i) == s2.charAt(j) ? 0 : 1), a[i - 1][j] + 1), a[i][j - 1] + 1); } } return a[s1.length() - 1][s2.length() - 1]; } @NotNull @Contract(pure = true) public static String wordsToBeginFromUpperCase(@NotNull String s) { return fixCapitalization(s, ourPrepositions, true); } @NotNull @Contract(pure = true) public static String wordsToBeginFromLowerCase(@NotNull String s) { return fixCapitalization(s, ourPrepositions, false); } @NotNull @Contract(pure = true) public static String toTitleCase(@NotNull String s) { return fixCapitalization(s, ArrayUtil.EMPTY_STRING_ARRAY, true); } @NotNull private static String fixCapitalization(@NotNull String s, @NotNull String[] prepositions, boolean title) { StringBuilder buffer = null; for (int i = 0; i < s.length(); i++) { char prevChar = i == 0 ? ' ' : s.charAt(i - 1); char currChar = s.charAt(i); if (!Character.isLetterOrDigit(prevChar) && prevChar != '\'') { if (Character.isLetterOrDigit(currChar)) { if (title || Character.isUpperCase(currChar)) { int j = i; for (; j < s.length(); j++) { if (!Character.isLetterOrDigit(s.charAt(j))) { break; } } if (!title && j > i + 1 && !Character.isLowerCase(s.charAt(i + 1))) { // filter out abbreviations like I18n, SQL and CSS continue; } if (!isPreposition(s, i, j - 1, prepositions)) { if (buffer == null) { buffer = new StringBuilder(s); } buffer.setCharAt(i, title ? toUpperCase(currChar) : toLowerCase(currChar)); } } } } } return buffer == null ? s : buffer.toString(); } private static final String[] ourPrepositions = { "a", "an", "and", "as", "at", "but", "by", "down", "for", "from", "if", "in", "into", "not", "of", "on", "onto", "or", "out", "over", "per", "nor", "the", "to", "up", "upon", "via", "with" }; @Contract(pure = true) public static boolean isPreposition(@NotNull String s, int firstChar, int lastChar) { return isPreposition(s, firstChar, lastChar, ourPrepositions); } @Contract(pure = true) public static boolean isPreposition(@NotNull String s, int firstChar, int lastChar, @NotNull String[] prepositions) { for (String preposition : prepositions) { boolean found = false; if (lastChar - firstChar + 1 == preposition.length()) { found = true; for (int j = 0; j < preposition.length(); j++) { if (toLowerCase(s.charAt(firstChar + j)) != preposition.charAt(j)) { found = false; } } } if (found) { return true; } } return false; } @NotNull @Contract(pure = true) public static NotNullFunction escaper(final boolean escapeSlash, @Nullable final String additionalChars) { return new NotNullFunction() { @NotNull @Override public String fun(@NotNull String dom) { final StringBuilder builder = new StringBuilder(dom.length()); escapeStringCharacters(dom.length(), dom, additionalChars, escapeSlash, builder); return builder.toString(); } }; } public static void escapeStringCharacters(int length, @NotNull String str, @NotNull StringBuilder buffer) { escapeStringCharacters(length, str, "\"", buffer); } @NotNull public static StringBuilder escapeStringCharacters(int length, @NotNull String str, @Nullable String additionalChars, @NotNull StringBuilder buffer) { return escapeStringCharacters(length, str, additionalChars, true, buffer); } @NotNull public static StringBuilder escapeStringCharacters(int length, @NotNull String str, @Nullable String additionalChars, boolean escapeSlash, @NotNull StringBuilder buffer) { return escapeStringCharacters(length, str, additionalChars, escapeSlash, true, buffer); } @NotNull public static StringBuilder escapeStringCharacters(int length, @NotNull String str, @Nullable String additionalChars, boolean escapeSlash, boolean escapeUnicode, @NotNull StringBuilder buffer) { char prev = 0; for (int idx = 0; idx < length; idx++) { char ch = str.charAt(idx); switch (ch) { case '\b': buffer.append("\\b"); break; case '\t': buffer.append("\\t"); break; case '\n': buffer.append("\\n"); break; case '\f': buffer.append("\\f"); break; case '\r': buffer.append("\\r"); break; default: if (escapeSlash && ch == '\\') { buffer.append("\\\\"); } else if (additionalChars != null && additionalChars.indexOf(ch) > -1 && (escapeSlash || prev != '\\')) { buffer.append("\\").append(ch); } else if (escapeUnicode && !isPrintableUnicode(ch)) { CharSequence hexCode = toUpperCase(Integer.toHexString(ch)); buffer.append("\\u"); int paddingCount = 4 - hexCode.length(); while (paddingCount-- > 0) { buffer.append(0); } buffer.append(hexCode); } else { buffer.append(ch); } } prev = ch; } return buffer; } @Contract(pure = true) public static boolean isPrintableUnicode(char c) { int t = Character.getType(c); return t != Character.UNASSIGNED && t != Character.LINE_SEPARATOR && t != Character.PARAGRAPH_SEPARATOR && t != Character.CONTROL && t != Character.FORMAT && t != Character.PRIVATE_USE && t != Character.SURROGATE; } @NotNull @Contract(pure = true) public static String escapeStringCharacters(@NotNull String s) { StringBuilder buffer = new StringBuilder(s.length()); escapeStringCharacters(s.length(), s, "\"", buffer); return buffer.toString(); } @NotNull @Contract(pure = true) public static String escapeCharCharacters(@NotNull String s) { StringBuilder buffer = new StringBuilder(s.length()); escapeStringCharacters(s.length(), s, "\'", buffer); return buffer.toString(); } @NotNull @Contract(pure = true) public static String unescapeStringCharacters(@NotNull String s) { StringBuilder buffer = new StringBuilder(s.length()); unescapeStringCharacters(s.length(), s, buffer); return buffer.toString(); } private static boolean isQuoteAt(@NotNull String s, int ind) { char ch = s.charAt(ind); return ch == '\'' || ch == '\"'; } @Contract(pure = true) public static boolean isQuotedString(@NotNull String s) { return StringUtilRt.isQuotedString(s); } @NotNull @Contract(pure = true) public static String unquoteString(@NotNull String s) { return StringUtilRt.unquoteString(s); } private static void unescapeStringCharacters(int length, @NotNull String s, @NotNull StringBuilder buffer) { boolean escaped = false; for (int idx = 0; idx < length; idx++) { char ch = s.charAt(idx); if (!escaped) { if (ch == '\\') { escaped = true; } else { buffer.append(ch); } } else { int octalEscapeMaxLength = 2; switch (ch) { case 'n': buffer.append('\n'); break; case 'r': buffer.append('\r'); break; case 'b': buffer.append('\b'); break; case 't': buffer.append('\t'); break; case 'f': buffer.append('\f'); break; case '\'': buffer.append('\''); break; case '\"': buffer.append('\"'); break; case '\\': buffer.append('\\'); break; case 'u': if (idx + 4 < length) { try { int code = Integer.parseInt(s.substring(idx + 1, idx + 5), 16); //noinspection AssignmentToForLoopParameter idx += 4; buffer.append((char)code); } catch (NumberFormatException e) { buffer.append("\\u"); } } else { buffer.append("\\u"); } break; case '0': case '1': case '2': case '3': octalEscapeMaxLength = 3; //noinspection fallthrough case '4': case '5': case '6': case '7': int escapeEnd = idx + 1; while (escapeEnd < length && escapeEnd < idx + octalEscapeMaxLength && isOctalDigit(s.charAt(escapeEnd))) escapeEnd++; try { buffer.append((char)Integer.parseInt(s.substring(idx, escapeEnd), 8)); } catch (NumberFormatException e) { throw new RuntimeException("Couldn't parse " + s.substring(idx, escapeEnd), e); // shouldn't happen } //noinspection AssignmentToForLoopParameter idx = escapeEnd - 1; break; default: buffer.append(ch); break; } escaped = false; } } if (escaped) buffer.append('\\'); } // @NotNull // @Contract(pure = true) // public static String pluralize(@NotNull String word) { // String plural = Pluralizer.PLURALIZER.plural(word); // if (plural != null) return plural; // if (word.endsWith("s")) return Pluralizer.restoreCase(word, word + "es"); // return Pluralizer.restoreCase(word, word + "s"); // } @NotNull @Contract(pure = true) public static String capitalizeWords(@NotNull String text, boolean allWords) { return capitalizeWords(text, " \t\n\r\f", allWords, false); } @NotNull @Contract(pure = true) public static String capitalizeWords(@NotNull String text, @NotNull String tokenizerDelim, boolean allWords, boolean leaveOriginalDelims) { final StringTokenizer tokenizer = new StringTokenizer(text, tokenizerDelim, leaveOriginalDelims); final StringBuilder out = new StringBuilder(text.length()); boolean toCapitalize = true; while (tokenizer.hasMoreTokens()) { final String word = tokenizer.nextToken(); if (!leaveOriginalDelims && out.length() > 0) { out.append(' '); } out.append(toCapitalize ? capitalize(word) : word); if (!allWords) { toCapitalize = false; } } return out.toString(); } @NotNull @Contract(pure = true) public static String decapitalize(@NotNull String s) { return Introspector.decapitalize(s); } @Contract(pure = true) public static boolean isVowel(char c) { return VOWELS.indexOf(c) >= 0; } /** * Capitalize the first letter of the sentence. */ @NotNull @Contract(pure = true) public static String capitalize(@NotNull String s) { if (s.isEmpty()) return s; if (s.length() == 1) return toUpperCase(s).toString(); // Optimization if (Character.isUpperCase(s.charAt(0))) return s; return toUpperCase(s.charAt(0)) + s.substring(1); } @Contract(value = "null -> false", pure = true) public static boolean isCapitalized(@Nullable String s) { return s != null && !s.isEmpty() && Character.isUpperCase(s.charAt(0)); } @NotNull @Contract(pure = true) public static String capitalizeWithJavaBeanConvention(@NotNull String s) { if (s.length() > 1 && Character.isUpperCase(s.charAt(1))) { return s; } return capitalize(s); } @Contract(pure = true) public static int stringHashCode(@NotNull CharSequence chars) { if (chars instanceof String || chars instanceof CharSequenceWithStringHash) { // we know for sure these classes have conformant (and maybe faster) hashCode() return chars.hashCode(); } return stringHashCode(chars, 0, chars.length()); } @Contract(pure = true) public static int stringHashCode(@NotNull CharSequence chars, int from, int to) { int h = 0; for (int off = from; off < to; off++) { h = 31 * h + chars.charAt(off); } return h; } @Contract(pure = true) public static int stringHashCode(char[] chars, int from, int to) { int h = 0; for (int off = from; off < to; off++) { h = 31 * h + chars[off]; } return h; } @Contract(pure = true) public static int stringHashCodeInsensitive(@NotNull char[] chars, int from, int to) { int h = 0; for (int off = from; off < to; off++) { h = 31 * h + toLowerCase(chars[off]); } return h; } @Contract(pure = true) public static int stringHashCodeInsensitive(@NotNull CharSequence chars, int from, int to) { int h = 0; for (int off = from; off < to; off++) { h = 31 * h + toLowerCase(chars.charAt(off)); } return h; } @Contract(pure = true) public static int stringHashCodeInsensitive(@NotNull CharSequence chars) { return stringHashCodeInsensitive(chars, 0, chars.length()); } @Contract(pure = true) public static int stringHashCodeIgnoreWhitespaces(@NotNull char[] chars, int from, int to) { int h = 0; for (int off = from; off < to; off++) { char c = chars[off]; if (!isWhiteSpace(c)) { h = 31 * h + c; } } return h; } @Contract(pure = true) public static int stringHashCodeIgnoreWhitespaces(@NotNull CharSequence chars, int from, int to) { int h = 0; for (int off = from; off < to; off++) { char c = chars.charAt(off); if (!isWhiteSpace(c)) { h = 31 * h + c; } } return h; } @Contract(pure = true) public static int stringHashCodeIgnoreWhitespaces(@NotNull CharSequence chars) { return stringHashCodeIgnoreWhitespaces(chars, 0, chars.length()); } /** * Equivalent to string.startsWith(prefixes[0] + prefixes[1] + ...) but avoids creating an object for concatenation. */ @Contract(pure = true) public static boolean startsWithConcatenation(@NotNull String string, @NotNull String... prefixes) { int offset = 0; for (String prefix : prefixes) { int prefixLen = prefix.length(); if (!string.regionMatches(offset, prefix, 0, prefixLen)) { return false; } offset += prefixLen; } return true; } @Contract(value = "null -> null; !null -> !null", pure = true) public static String trim(@Nullable String s) { return s == null ? null : s.trim(); } @NotNull @Contract(pure = true) public static String trimEnd(@NotNull String s, @NotNull String suffix) { return trimEnd(s, suffix, false); } @NotNull @Contract(pure = true) public static String trimEnd(@NotNull String s, @NotNull String suffix, boolean ignoreCase) { boolean endsWith = ignoreCase ? endsWithIgnoreCase(s, suffix) : s.endsWith(suffix); if (endsWith) { return s.substring(0, s.length() - suffix.length()); } return s; } @NotNull @Contract(pure = true) public static String trimEnd(@NotNull String s, char suffix) { if (endsWithChar(s, suffix)) { return s.substring(0, s.length() - 1); } return s; } @NotNull @Contract(pure = true) public static String trimLog(@NotNull final String text, final int limit) { if (limit > 5 && text.length() > limit) { return text.substring(0, limit - 5) + " ...\n"; } return text; } @NotNull @Contract(pure = true) public static String trimLeading(@NotNull String string) { return trimLeading((CharSequence)string).toString(); } @NotNull @Contract(pure = true) public static CharSequence trimLeading(@NotNull CharSequence string) { int index = 0; while (index < string.length() && Character.isWhitespace(string.charAt(index))) index++; return string.subSequence(index, string.length()); } @NotNull @Contract(pure = true) public static String trimLeading(@NotNull String string, char symbol) { int index = 0; while (index < string.length() && string.charAt(index) == symbol) index++; return string.substring(index); } @NotNull public static StringBuilder trimLeading(@NotNull StringBuilder builder, char symbol) { int index = 0; while (index < builder.length() && builder.charAt(index) == symbol) index++; if (index > 0) builder.delete(0, index); return builder; } @NotNull @Contract(pure = true) public static String trimTrailing(@NotNull String string) { return trimTrailing((CharSequence)string).toString(); } @NotNull @Contract(pure = true) public static CharSequence trimTrailing(@NotNull CharSequence string) { int index = string.length() - 1; while (index >= 0 && Character.isWhitespace(string.charAt(index))) index--; return string.subSequence(0, index + 1); } @NotNull @Contract(pure = true) public static String trimTrailing(@NotNull String string, char symbol) { int index = string.length() - 1; while (index >= 0 && string.charAt(index) == symbol) index--; return string.substring(0, index + 1); } @NotNull public static StringBuilder trimTrailing(@NotNull StringBuilder builder, char symbol) { int index = builder.length() - 1; while (index >= 0 && builder.charAt(index) == symbol) index--; builder.setLength(index + 1); return builder; } @Contract(pure = true) public static boolean startsWithChar(@Nullable CharSequence s, char prefix) { return s != null && s.length() != 0 && s.charAt(0) == prefix; } @Contract(pure = true) public static boolean endsWithChar(@Nullable CharSequence s, char suffix) { return StringUtilRt.endsWithChar(s, suffix); } @NotNull @Contract(pure = true) public static String trimStart(@NotNull String s, @NotNull String prefix) { if (s.startsWith(prefix)) { return s.substring(prefix.length()); } return s; } @NotNull @Contract(pure = true) public static String trimExtensions(@NotNull String name) { int index = name.indexOf('.'); return index < 0 ? name : name.substring(0, index); } // @NotNull // @Contract(pure = true) // public static String pluralize(@NotNull String base, int count) { // if (count == 1) return base; // return pluralize(base); // } public static void repeatSymbol(@NotNull Appendable buffer, char symbol, int times) { assert times >= 0 : times; try { for (int i = 0; i < times; i++) { buffer.append(symbol); } } catch (IOException e) { LOG.error(e); } } @Contract(pure = true) public static String defaultIfEmpty(@Nullable String value, String defaultValue) { return isEmpty(value) ? defaultValue : value; } @Contract(value = "null -> false", pure = true) public static boolean isNotEmpty(@Nullable String s) { return !isEmpty(s); } @Contract(value = "null -> true", pure = true) public static boolean isEmpty(@Nullable String s) { return s == null || s.isEmpty(); } @Contract(value = "null -> true",pure = true) public static boolean isEmpty(@Nullable CharSequence cs) { return StringUtilRt.isEmpty(cs); } @Contract(pure = true) public static int length(@Nullable CharSequence cs) { return cs == null ? 0 : cs.length(); } @NotNull @Contract(pure = true) public static String notNullize(@Nullable String s) { return StringUtilRt.notNullize(s); } @NotNull @Contract(pure = true) public static String notNullize(@Nullable String s, @NotNull String defaultValue) { return StringUtilRt.notNullize(s, defaultValue); } @Nullable @Contract(pure = true) public static String nullize(@Nullable String s) { return nullize(s, false); } @Nullable @Contract(pure = true) public static String nullize(@Nullable String s, boolean nullizeSpaces) { boolean empty = nullizeSpaces ? isEmptyOrSpaces(s) : isEmpty(s); return empty ? null : s; } @Contract(value = "null -> true",pure = true) // we need to keep this method to preserve backward compatibility public static boolean isEmptyOrSpaces(@Nullable String s) { return isEmptyOrSpaces((CharSequence)s); } @Contract(value = "null -> true", pure = true) public static boolean isEmptyOrSpaces(@Nullable CharSequence s) { return StringUtilRt.isEmptyOrSpaces(s); } /** * Allows to answer if given symbol is white space, tabulation or line feed. * * @param c symbol to check * @return {@code true} if given symbol is white space, tabulation or line feed; {@code false} otherwise */ @Contract(pure = true) public static boolean isWhiteSpace(char c) { return c == '\n' || c == '\t' || c == ' '; } @NotNull @Contract(pure = true) public static String getThrowableText(@NotNull Throwable aThrowable) { return ExceptionUtil.getThrowableText(aThrowable); } @NotNull @Contract(pure = true) public static String repeatSymbol(final char aChar, final int count) { char[] buffer = new char[count]; Arrays.fill(buffer, aChar); return StringFactory.createShared(buffer); } @NotNull @Contract(pure = true) public static String repeat(@NotNull String s, int count) { assert count >= 0 : count; StringBuilder sb = new StringBuilder(s.length() * count); for (int i = 0; i < count; i++) { sb.append(s); } return sb.toString(); } @NotNull @Contract(pure = true) public static List split(@NotNull String s, @NotNull String separator) { return split(s, separator, true); } @NotNull @Contract(pure = true) public static List split(@NotNull CharSequence s, @NotNull CharSequence separator) { return split(s, separator, true, true); } @NotNull @Contract(pure = true) public static List split(@NotNull String s, @NotNull String separator, boolean excludeSeparator) { return split(s, separator, excludeSeparator, true); } @NotNull @Contract(pure = true) @SuppressWarnings("unchecked") public static List split(@NotNull String s, @NotNull String separator, boolean excludeSeparator, boolean excludeEmptyStrings) { return (List)split((CharSequence)s, separator, excludeSeparator, excludeEmptyStrings); } @NotNull @Contract(pure = true) public static List split(@NotNull CharSequence s, @NotNull CharSequence separator, boolean excludeSeparator, boolean excludeEmptyStrings) { if (separator.length() == 0) { return Collections.singletonList(s); } List result = new ArrayList(); int pos = 0; while (true) { int index = indexOf(s, separator, pos); if (index == -1) break; final int nextPos = index + separator.length(); CharSequence token = s.subSequence(pos, excludeSeparator ? index : nextPos); if (token.length() != 0 || !excludeEmptyStrings) { result.add(token); } pos = nextPos; } if (pos < s.length() || !excludeEmptyStrings && pos == s.length()) { result.add(s.subSequence(pos, s.length())); } return result; } @NotNull @Contract(pure = true) public static Iterable tokenize(@NotNull String s, @NotNull String separators) { final com.intellij.util.text.StringTokenizer tokenizer = new com.intellij.util.text.StringTokenizer(s, separators); return new Iterable() { @NotNull @Override public Iterator iterator() { return new Iterator() { @Override public boolean hasNext() { return tokenizer.hasMoreTokens(); } @Override public String next() { return tokenizer.nextToken(); } @Override public void remove() { throw new UnsupportedOperationException(); } }; } }; } @NotNull @Contract(pure = true) public static Iterable tokenize(@NotNull final StringTokenizer tokenizer) { return new Iterable() { @NotNull @Override public Iterator iterator() { return new Iterator() { @Override public boolean hasNext() { return tokenizer.hasMoreTokens(); } @Override public String next() { return tokenizer.nextToken(); } @Override public void remove() { throw new UnsupportedOperationException(); } }; } }; } /** * @return list containing all words in {@code text}, or {@link ContainerUtil#emptyList()} if there are none. * The word here means the maximum sub-string consisting entirely of characters which are {@code Character.isJavaIdentifierPart(c)}. */ @NotNull @Contract(pure = true) public static List getWordsIn(@NotNull String text) { List result = null; int start = -1; for (int i = 0; i < text.length(); i++) { char c = text.charAt(i); boolean isIdentifierPart = Character.isJavaIdentifierPart(c); if (isIdentifierPart && start == -1) { start = i; } if (isIdentifierPart && i == text.length() - 1) { if (result == null) { result = new SmartList(); } result.add(text.substring(start, i + 1)); } else if (!isIdentifierPart && start != -1) { if (result == null) { result = new SmartList(); } result.add(text.substring(start, i)); start = -1; } } if (result == null) { return ContainerUtil.emptyList(); } return result; } @NotNull @Contract(pure = true) public static List getWordIndicesIn(@NotNull String text) { return getWordIndicesIn(text, null); } /** * @param text text to get word ranges in. * @param separatorsSet if not null, only these characters will be considered as separators (i.e. not a part of word). * Otherwise {@link Character#isJavaIdentifierPart(char)} will be used to determine whether a symbol is part of word. * @return ranges ranges of words in passed text. */ @NotNull @Contract(pure = true) public static List getWordIndicesIn(@NotNull String text, @Nullable Set separatorsSet) { List result = new SmartList(); int start = -1; for (int i = 0; i < text.length(); i++) { char c = text.charAt(i); boolean isIdentifierPart = separatorsSet == null ? Character.isJavaIdentifierPart(c) : !separatorsSet.contains(c); if (isIdentifierPart && start == -1) { start = i; } if (isIdentifierPart && i == text.length() - 1) { result.add(new TextRange(start, i + 1)); } else if (!isIdentifierPart && start != -1) { result.add(new TextRange(start, i)); start = -1; } } return result; } @NotNull @Contract(pure = true) public static String join(@NotNull final String[] strings, @NotNull final String separator) { return join(strings, 0, strings.length, separator); } @NotNull @Contract(pure = true) public static String join(@NotNull final String[] strings, int startIndex, int endIndex, @NotNull final String separator) { final StringBuilder result = new StringBuilder(); for (int i = startIndex; i < endIndex; i++) { if (i > startIndex) result.append(separator); result.append(strings[i]); } return result.toString(); } @NotNull @Contract(pure = true) public static String[] zip(@NotNull String[] strings1, @NotNull String[] strings2, String separator) { if (strings1.length != strings2.length) throw new IllegalArgumentException(); String[] result = ArrayUtil.newStringArray(strings1.length); for (int i = 0; i < result.length; i++) { result[i] = strings1[i] + separator + strings2[i]; } return result; } @NotNull @Contract(pure = true) public static String[] surround(@NotNull String[] strings, @NotNull String prefix, @NotNull String suffix) { String[] result = ArrayUtil.newStringArray(strings.length); for (int i = 0; i < result.length; i++) { result[i] = prefix + strings[i] + suffix; } return result; } @NotNull @Contract(pure = true) public static String join(@NotNull T[] items, @NotNull Function f, @NotNull String separator) { return join(Arrays.asList(items), f, separator); } @NotNull @Contract(pure = true) public static String join(@NotNull Collection items, @NotNull Function f, @NotNull String separator) { if (items.isEmpty()) return ""; if (items.size() == 1) return notNullize(f.fun(items.iterator().next())); return join((Iterable)items, f, separator); } @Contract(pure = true) public static String join(@NotNull Iterable items, @NotNull String separator) { StringBuilder result = new StringBuilder(); for (Object item : items) { result.append(item).append(separator); } if (result.length() > 0) { result.setLength(result.length() - separator.length()); } return result.toString(); } @NotNull @Contract(pure = true) public static String join(@NotNull Iterable items, @NotNull Function f, @NotNull String separator) { StringBuilder result = new StringBuilder(); join(items, f, separator, result); return result.toString(); } public static void join(@NotNull Iterable items, @NotNull Function f, @NotNull String separator, @NotNull StringBuilder result) { boolean isFirst = true; for (T item : items) { String string = f.fun(item); if (!isEmpty(string)) { if (isFirst) { isFirst = false; } else { result.append(separator); } result.append(string); } } } @NotNull @Contract(pure = true) public static String join(@NotNull Collection strings, @NotNull String separator) { if (strings.size() <= 1) { return notNullize(ContainerUtil.getFirstItem(strings)); } StringBuilder result = new StringBuilder(); join(strings, separator, result); return result.toString(); } public static void join(@NotNull Collection strings, @NotNull String separator, @NotNull StringBuilder result) { boolean isFirst = true; for (String string : strings) { if (string != null) { if (isFirst) { isFirst = false; } else { result.append(separator); } result.append(string); } } } @NotNull @Contract(pure = true) public static String join(@NotNull final int[] strings, @NotNull final String separator) { final StringBuilder result = new StringBuilder(); for (int i = 0; i < strings.length; i++) { if (i > 0) result.append(separator); result.append(strings[i]); } return result.toString(); } @NotNull @Contract(pure = true) public static String join(@NotNull final String... strings) { if (strings.length == 0) return ""; final StringBuilder builder = new StringBuilder(); for (final String string : strings) { builder.append(string); } return builder.toString(); } /** * Consider using {@link StringUtil#unquoteString(String)} instead. * Note: this method has an odd behavior: * Quotes are removed even if leading and trailing quotes are different or * if there is only one quote (leading or trailing). */ @NotNull @Contract(pure = true) public static String stripQuotesAroundValue(@NotNull String text) { final int len = text.length(); if (len > 0) { final int from = isQuoteAt(text, 0) ? 1 : 0; final int to = len > 1 && isQuoteAt(text, len - 1) ? len - 1 : len; if (from > 0 || to < len) { return text.substring(from, to); } } return text; } /** Formats given duration as a sum of time units (example: {@code formatDuration(123456) = "2 m 3 s 456 ms"}). */ @NotNull @Contract(pure = true) public static String formatDuration(long duration) { return formatDuration(duration, " "); } private static final String[] TIME_UNITS = {"ms", "s", "m", "h", "d", "mo", "yr", "c", "ml", "ep"}; private static final long[] TIME_MULTIPLIERS = {1, 1000, 60, 60, 24, 30, 12, 100, 10, 10000}; /** Formats given duration as a sum of time units (example: {@code formatDuration(123456, "") = "2m 3s 456ms"}). */ @NotNull @Contract(pure = true) public static String formatDuration(long duration, @NotNull String unitSeparator) { String[] units = TIME_UNITS; StringBuilder sb = new StringBuilder(); long count = duration; int i = 1; for (; i < units.length && count > 0; i++) { long multiplier = TIME_MULTIPLIERS[i]; if (count < multiplier) break; long remainder = count % multiplier; count /= multiplier; if (remainder != 0 || sb.length() > 0) { if (!units[i - 1].isEmpty()) { sb.insert(0, units[i - 1]); sb.insert(0, unitSeparator); } sb.insert(0, remainder).insert(0, " "); } else { remainder = Math.round(remainder * 100 / (double)multiplier); count += remainder / 100; } } if (!units[i - 1].isEmpty()) { sb.insert(0, units[i - 1]); sb.insert(0, unitSeparator); } sb.insert(0, count); return sb.toString(); } @Contract(pure = true) public static boolean containsAlphaCharacters(@NotNull String value) { for (int i = 0; i < value.length(); i++) { if (Character.isLetter(value.charAt(i))) return true; } return false; } @Contract(pure = true) public static boolean containsAnyChar(@NotNull final String value, @NotNull final String chars) { return chars.length() > value.length() ? containsAnyChar(value, chars, 0, value.length()) : containsAnyChar(chars, value, 0, chars.length()); } @Contract(pure = true) public static boolean containsAnyChar(@NotNull final String value, @NotNull final String chars, final int start, final int end) { for (int i = start; i < end; i++) { if (chars.indexOf(value.charAt(i)) >= 0) { return true; } } return false; } @Contract(pure = true) public static boolean containsChar(@NotNull final String value, final char ch) { return value.indexOf(ch) >= 0; } /** * @deprecated use #capitalize(String) */ @Deprecated @Contract(value = "null -> null; !null -> !null", pure = true) public static String firstLetterToUpperCase(@Nullable final String displayString) { if (displayString == null || displayString.isEmpty()) return displayString; char firstChar = displayString.charAt(0); char uppedFirstChar = toUpperCase(firstChar); if (uppedFirstChar == firstChar) return displayString; char[] buffer = displayString.toCharArray(); buffer[0] = uppedFirstChar; return StringFactory.createShared(buffer); } /** * Strip out all characters not accepted by given filter * * @param s e.g. "/n my string " * @param filter e.g. {@link CharFilter#NOT_WHITESPACE_FILTER} * @return stripped string e.g. "mystring" */ @NotNull @Contract(pure = true) public static String strip(@NotNull final String s, @NotNull final CharFilter filter) { final StringBuilder result = new StringBuilder(s.length()); for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); if (filter.accept(ch)) { result.append(ch); } } return result.toString(); } @NotNull @Contract(pure = true) public static List findMatches(@NotNull String s, @NotNull Pattern pattern) { return findMatches(s, pattern, 1); } @NotNull @Contract(pure = true) public static List findMatches(@NotNull String s, @NotNull Pattern pattern, int groupIndex) { List result = new SmartList(); Matcher m = pattern.matcher(s); while (m.find()) { String group = m.group(groupIndex); if (group != null) { result.add(group); } } return result; } /** * Find position of the first character accepted by given filter. * * @param s the string to search * @param filter search filter * @return position of the first character accepted or -1 if not found */ @Contract(pure = true) public static int findFirst(@NotNull final CharSequence s, @NotNull CharFilter filter) { for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); if (filter.accept(ch)) { return i; } } return -1; } @NotNull @Contract(pure = true) public static String replaceSubstring(@NotNull String string, @NotNull TextRange range, @NotNull String replacement) { return range.replace(string, replacement); } @Contract(pure = true) public static boolean startsWithWhitespace(@NotNull String text) { return !text.isEmpty() && Character.isWhitespace(text.charAt(0)); } @Contract(pure = true) public static boolean isChar(CharSequence seq, int index, char c) { return index >= 0 && index < seq.length() && seq.charAt(index) == c; } @Contract(pure = true) public static boolean startsWith(@NotNull CharSequence text, @NotNull CharSequence prefix) { int l1 = text.length(); int l2 = prefix.length(); if (l1 < l2) return false; for (int i = 0; i < l2; i++) { if (text.charAt(i) != prefix.charAt(i)) return false; } return true; } @Contract(pure = true) public static boolean startsWith(@NotNull CharSequence text, int startIndex, @NotNull CharSequence prefix) { int tl = text.length(); if (startIndex < 0 || startIndex > tl) { throw new IllegalArgumentException("Index is out of bounds: " + startIndex + ", length: " + tl); } int l1 = tl - startIndex; int l2 = prefix.length(); if (l1 < l2) return false; for (int i = 0; i < l2; i++) { if (text.charAt(i + startIndex) != prefix.charAt(i)) return false; } return true; } @Contract(pure = true) public static boolean endsWith(@NotNull CharSequence text, @NotNull CharSequence suffix) { int l1 = text.length(); int l2 = suffix.length(); if (l1 < l2) return false; for (int i = l1 - 1; i >= l1 - l2; i--) { if (text.charAt(i) != suffix.charAt(i + l2 - l1)) return false; } return true; } @NotNull @Contract(pure = true) public static String commonPrefix(@NotNull String s1, @NotNull String s2) { return s1.substring(0, commonPrefixLength(s1, s2)); } @Contract(pure = true) public static int commonPrefixLength(@NotNull CharSequence s1, @NotNull CharSequence s2) { return commonPrefixLength(s1, s2, false); } @Contract(pure = true) public static int commonPrefixLength(@NotNull CharSequence s1, @NotNull CharSequence s2, boolean ignoreCase) { int i; int minLength = Math.min(s1.length(), s2.length()); for (i = 0; i < minLength; i++) { if (!charsMatch(s1.charAt(i), s2.charAt(i), ignoreCase)) { break; } } return i; } @NotNull @Contract(pure = true) public static String commonSuffix(@NotNull String s1, @NotNull String s2) { return s1.substring(s1.length() - commonSuffixLength(s1, s2)); } @Contract(pure = true) public static int commonSuffixLength(@NotNull CharSequence s1, @NotNull CharSequence s2) { int s1Length = s1.length(); int s2Length = s2.length(); if (s1Length == 0 || s2Length == 0) return 0; int i; for (i = 0; i < s1Length && i < s2Length; i++) { if (s1.charAt(s1Length - i - 1) != s2.charAt(s2Length - i - 1)) { break; } } return i; } /** * Allows to answer if target symbol is contained at given char sequence at {@code [start; end)} interval. * * @param s target char sequence to check * @param start start offset to use within the given char sequence (inclusive) * @param end end offset to use within the given char sequence (exclusive) * @param c target symbol to check * @return {@code true} if given symbol is contained at the target range of the given char sequence; * {@code false} otherwise */ @Contract(pure = true) public static boolean contains(@NotNull CharSequence s, int start, int end, char c) { return indexOf(s, c, start, end) >= 0; } @Contract(pure = true) public static boolean containsWhitespaces(@Nullable CharSequence s) { if (s == null) return false; for (int i = 0; i < s.length(); i++) { if (Character.isWhitespace(s.charAt(i))) return true; } return false; } @Contract(pure = true) public static int indexOf(@NotNull CharSequence s, char c) { return indexOf(s, c, 0, s.length()); } @Contract(pure = true) public static int indexOf(@NotNull CharSequence s, char c, int start) { return indexOf(s, c, start, s.length()); } @Contract(pure = true) public static int indexOf(@NotNull CharSequence s, char c, int start, int end) { end = Math.min(end, s.length()); for (int i = Math.max(start, 0); i < end; i++) { if (s.charAt(i) == c) return i; } return -1; } @Contract(pure = true) public static boolean contains(@NotNull CharSequence sequence, @NotNull CharSequence infix) { return indexOf(sequence, infix) >= 0; } @Contract(pure = true) public static int indexOf(@NotNull CharSequence sequence, @NotNull CharSequence infix) { return indexOf(sequence, infix, 0); } @Contract(pure = true) public static int indexOf(@NotNull CharSequence sequence, @NotNull CharSequence infix, int start) { return indexOf(sequence, infix, start, sequence.length()); } @Contract(pure = true) public static int indexOf(@NotNull CharSequence sequence, @NotNull CharSequence infix, int start, int end) { for (int i = start; i <= end - infix.length(); i++) { if (startsWith(sequence, i, infix)) { return i; } } return -1; } @Contract(pure = true) public static int indexOf(@NotNull CharSequence s, char c, int start, int end, boolean caseSensitive) { end = Math.min(end, s.length()); for (int i = Math.max(start, 0); i < end; i++) { if (charsMatch(s.charAt(i), c, !caseSensitive)) return i; } return -1; } @Contract(pure = true) public static int indexOf(@NotNull char[] s, char c, int start, int end, boolean caseSensitive) { end = Math.min(end, s.length); for (int i = Math.max(start, 0); i < end; i++) { if (charsMatch(s[i], c, !caseSensitive)) return i; } return -1; } @Contract(pure = true) public static int indexOfSubstringEnd(@NotNull String text, @NotNull String subString) { int i = text.indexOf(subString); if (i == -1) return -1; return i + subString.length(); } @Contract(pure = true) public static int indexOfAny(@NotNull final String s, @NotNull final String chars) { return indexOfAny(s, chars, 0, s.length()); } @Contract(pure = true) public static int indexOfAny(@NotNull final CharSequence s, @NotNull final String chars) { return indexOfAny(s, chars, 0, s.length()); } @Contract(pure = true) public static int indexOfAny(@NotNull final String s, @NotNull final String chars, final int start, final int end) { return indexOfAny((CharSequence)s, chars, start, end); } @Contract(pure = true) public static int indexOfAny(@NotNull final CharSequence s, @NotNull final String chars, final int start, int end) { end = Math.min(end, s.length()); for (int i = Math.max(start, 0); i < end; i++) { if (containsChar(chars, s.charAt(i))) return i; } return -1; } @Contract(pure = true) public static int lastIndexOfAny(@NotNull CharSequence s, @NotNull final String chars) { for (int i = s.length() - 1; i >= 0; i--) { if (containsChar(chars, s.charAt(i))) return i; } return -1; } @Nullable @Contract(pure = true) public static String substringBefore(@NotNull String text, @NotNull String subString) { int i = text.indexOf(subString); if (i == -1) return null; return text.substring(0, i); } @NotNull @Contract(pure = true) public static String substringBeforeLast(@NotNull String text, @NotNull String subString) { int i = text.lastIndexOf(subString); if (i == -1) return text; return text.substring(0, i); } @Nullable @Contract(pure = true) public static String substringAfter(@NotNull String text, @NotNull String subString) { int i = text.indexOf(subString); if (i == -1) return null; return text.substring(i + subString.length()); } @Nullable @Contract(pure = true) public static String substringAfterLast(@NotNull String text, @NotNull String subString) { int i = text.lastIndexOf(subString); if (i == -1) return null; return text.substring(i + subString.length()); } /** * Allows to retrieve index of last occurrence of the given symbols at {@code [start; end)} sub-sequence of the given text. * * @param s target text * @param c target symbol which last occurrence we want to check * @param start start offset of the target text (inclusive) * @param end end offset of the target text (exclusive) * @return index of the last occurrence of the given symbol at the target sub-sequence of the given text if any; * {@code -1} otherwise */ @Contract(pure = true) public static int lastIndexOf(@NotNull CharSequence s, char c, int start, int end) { return StringUtilRt.lastIndexOf(s, c, start, end); } @NotNull @Contract(pure = true) public static String first(@NotNull String text, final int maxLength, final boolean appendEllipsis) { return text.length() > maxLength ? text.substring(0, maxLength) + (appendEllipsis ? "..." : "") : text; } @NotNull @Contract(pure = true) public static CharSequence first(@NotNull CharSequence text, final int length, final boolean appendEllipsis) { if (text.length() <= length) { return text; } if (appendEllipsis) { return text.subSequence(0, length) + "..."; } return text.subSequence(0, length); } @NotNull @Contract(pure = true) public static CharSequence last(@NotNull CharSequence text, final int length, boolean prependEllipsis) { if (text.length() <= length) { return text; } if (prependEllipsis) { return "..." + text.subSequence(text.length() - length, text.length()); } return text.subSequence(text.length() - length, text.length()); } @NotNull @Contract(pure = true) public static String firstLast(@NotNull String text, int length) { return text.length() > length ? text.subSequence(0, length / 2) + "\u2026" + text.subSequence(text.length() - length / 2 - 1, text.length()) : text; } @NotNull @Contract(pure = true) public static String escapeChar(@NotNull final String str, final char character) { return escapeChars(str, character); } @NotNull @Contract(pure = true) public static String escapeChars(@NotNull final String str, final char... character) { final StringBuilder buf = new StringBuilder(str); for (char c : character) { escapeChar(buf, c); } return buf.toString(); } public static void escapeChar(@NotNull final StringBuilder buf, final char character) { int idx = 0; while ((idx = indexOf(buf, character, idx)) >= 0) { buf.insert(idx, "\\"); idx += 2; } } @NotNull @Contract(pure = true) public static String escapeQuotes(@NotNull final String str) { return escapeChar(str, '"'); } public static void escapeQuotes(@NotNull final StringBuilder buf) { escapeChar(buf, '"'); } @NotNull @Contract(pure = true) public static String escapeSlashes(@NotNull final String str) { return escapeChar(str, '/'); } @NotNull @Contract(pure = true) public static String escapeBackSlashes(@NotNull final String str) { return escapeChar(str, '\\'); } public static void escapeSlashes(@NotNull final StringBuilder buf) { escapeChar(buf, '/'); } @NotNull @Contract(pure = true) public static String unescapeSlashes(@NotNull final String str) { final StringBuilder buf = new StringBuilder(str.length()); unescapeChar(buf, str, '/'); return buf.toString(); } @NotNull @Contract(pure = true) public static String unescapeBackSlashes(@NotNull final String str) { final StringBuilder buf = new StringBuilder(str.length()); unescapeChar(buf, str, '\\'); return buf.toString(); } @NotNull @Contract(pure = true) public static String unescapeChar(@NotNull final String str, char unescapeChar) { final StringBuilder buf = new StringBuilder(str.length()); unescapeChar(buf, str, unescapeChar); return buf.toString(); } private static void unescapeChar(@NotNull StringBuilder buf, @NotNull String str, char unescapeChar) { final int length = str.length(); final int last = length - 1; for (int i = 0; i < length; i++) { char ch = str.charAt(i); if (ch == '\\' && i != last) { //noinspection AssignmentToForLoopParameter i++; ch = str.charAt(i); if (ch != unescapeChar) buf.append('\\'); } buf.append(ch); } } public static void quote(@NotNull final StringBuilder builder) { quote(builder, '\"'); } public static void quote(@NotNull final StringBuilder builder, final char quotingChar) { builder.insert(0, quotingChar); builder.append(quotingChar); } @NotNull @Contract(pure = true) public static String wrapWithDoubleQuote(@NotNull String str) { return '\"' + str + "\""; } private static final List REPLACES_REFS = Arrays.asList("<", ">", "&", "'", """); private static final List REPLACES_DISP = Arrays.asList("<", ">", "&", "'", "\""); /** * @deprecated Use {@link #unescapeXmlEntities(String)} instead */ @Contract(value = "null -> null; !null -> !null",pure = true) @Deprecated public static String unescapeXml(@Nullable final String text) { return text == null ? null : unescapeXmlEntities(text); } /** * @deprecated Use {@link #escapeXmlEntities(String)} instead */ @Contract(value = "null -> null; !null -> !null",pure = true) @Deprecated public static String escapeXml(@Nullable final String text) { return text == null ? null : escapeXmlEntities(text); } /** * @return {@code text} with some standard XML entities replaced with corresponding characters, e.g. '{@code <}' replaced with '<' */ @NotNull @Contract(pure = true) public static String unescapeXmlEntities(@NotNull String text) { return replace(text, REPLACES_REFS, REPLACES_DISP); } /** * @return {@code text} with some characters replaced with standard XML entities, e.g. '<' replaced with '{@code <}' */ @NotNull @Contract(pure = true) public static String escapeXmlEntities(@NotNull String text) { return replace(text, REPLACES_DISP, REPLACES_REFS); } @NotNull public static String removeHtmlTags(@NotNull String htmlString) { return removeHtmlTags(htmlString, false); } @NotNull public static String removeHtmlTags(@NotNull String htmlString, boolean isRemoveStyleTag) { if (isEmpty(htmlString)) { return ""; } final MyHtml2Text parser = isRemoveStyleTag ? new MyHtml2Text(true) : html2TextParser; try { parser.parse(new StringReader(htmlString)); } catch (IOException e) { LOG.error(e); } return parser.getText(); } private static final List MN_QUOTED = Arrays.asList("&&", "__"); private static final List MN_CHARS = Arrays.asList("&", "_"); @NotNull @Contract(pure = true) public static String escapeMnemonics(@NotNull String text) { return replace(text, MN_CHARS, MN_QUOTED); } @NotNull @Contract(pure = true) public static String htmlEmphasize(@NotNull String text) { return "" + escapeXmlEntities(text) + ""; } @NotNull @Contract(pure = true) public static String escapeToRegexp(@NotNull String text) { final StringBuilder result = new StringBuilder(text.length()); return escapeToRegexp(text, result).toString(); } @NotNull public static StringBuilder escapeToRegexp(@NotNull CharSequence text, @NotNull StringBuilder builder) { for (int i = 0; i < text.length(); i++) { final char c = text.charAt(i); if (c == ' ' || Character.isLetter(c) || Character.isDigit(c) || c == '_') { builder.append(c); } else if (c == '\n') { builder.append("\\n"); } else if (c == '\r') { builder.append("\\r"); } else { builder.append('\\').append(c); } } return builder; } @Contract(pure = true) public static boolean isEscapedBackslash(@NotNull char[] chars, int startOffset, int backslashOffset) { if (chars[backslashOffset] != '\\') { return true; } boolean escaped = false; for (int i = startOffset; i < backslashOffset; i++) { if (chars[i] == '\\') { escaped = !escaped; } else { escaped = false; } } return escaped; } @Contract(pure = true) public static boolean isEscapedBackslash(@NotNull CharSequence text, int startOffset, int backslashOffset) { if (text.charAt(backslashOffset) != '\\') { return true; } boolean escaped = false; for (int i = startOffset; i < backslashOffset; i++) { if (text.charAt(i) == '\\') { escaped = !escaped; } else { escaped = false; } } return escaped; } /** * @deprecated Use {@link #replace(String, List, List)} */ @Deprecated @NotNull @Contract(pure = true) public static String replace(@NotNull String text, @NotNull String[] from, @NotNull String[] to) { return replace(text, Arrays.asList(from), Arrays.asList(to)); } @NotNull @Contract(pure = true) public static String replace(@NotNull String text, @NotNull List from, @NotNull List to) { assert from.size() == to.size(); StringBuilder result = null; replace: for (int i = 0; i < text.length(); i++) { for (int j = 0; j < from.size(); j += 1) { String toReplace = from.get(j); String replaceWith = to.get(j); final int len = toReplace.length(); if (text.regionMatches(i, toReplace, 0, len)) { if (result == null) { result = new StringBuilder(text.length()); result.append(text, 0, i); } result.append(replaceWith); //noinspection AssignmentToForLoopParameter i += len - 1; continue replace; } } if (result != null) { result.append(text.charAt(i)); } } return result == null ? text : result.toString(); } @NotNull @Contract(pure = true) public static String[] filterEmptyStrings(@NotNull String[] strings) { int emptyCount = 0; for (String string : strings) { if (string == null || string.isEmpty()) emptyCount++; } if (emptyCount == 0) return strings; String[] result = ArrayUtil.newStringArray(strings.length - emptyCount); int count = 0; for (String string : strings) { if (string == null || string.isEmpty()) continue; result[count++] = string; } return result; } @Contract(pure = true) public static int countNewLines(@NotNull CharSequence text) { return countChars(text, '\n'); } @Contract(pure = true) public static int countChars(@NotNull CharSequence text, char c) { return countChars(text, c, 0, false); } @Contract(pure = true) public static int countChars(@NotNull CharSequence text, char c, int offset, boolean stopAtOtherChar) { return countChars(text, c, offset, text.length(), stopAtOtherChar); } @Contract(pure = true) public static int countChars(@NotNull CharSequence text, char c, int start, int end, boolean stopAtOtherChar) { boolean forward = start <= end; start = forward ? Math.max(0, start) : Math.min(text.length(), start); end = forward ? Math.min(text.length(), end) : Math.max(0, end); int count = 0; for (int i = forward ? start : start - 1; forward == i < end; i += forward ? 1 : -1) { if (text.charAt(i) == c) { count++; } else if (stopAtOtherChar) { break; } } return count; } @NotNull @Contract(pure = true) public static String capitalsOnly(@NotNull String s) { StringBuilder b = new StringBuilder(); for (int i = 0; i < s.length(); i++) { if (Character.isUpperCase(s.charAt(i))) { b.append(s.charAt(i)); } } return b.toString(); } /** * @param args Strings to join. * @return {@code null} if any of given Strings is {@code null}. */ @Nullable @Contract(pure = true) public static String joinOrNull(@NotNull String... args) { StringBuilder r = new StringBuilder(); for (String arg : args) { if (arg == null) return null; r.append(arg); } return r.toString(); } @Nullable @Contract(pure = true) public static String getPropertyName(@NotNull String methodName) { if (methodName.startsWith("get")) { return Introspector.decapitalize(methodName.substring(3)); } if (methodName.startsWith("is")) { return Introspector.decapitalize(methodName.substring(2)); } if (methodName.startsWith("set")) { return Introspector.decapitalize(methodName.substring(3)); } return null; } @Contract(pure = true) public static boolean isJavaIdentifierStart(char c) { return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || Character.isJavaIdentifierStart(c); } @Contract(pure = true) public static boolean isJavaIdentifierPart(char c) { return c >= '0' && c <= '9' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || Character.isJavaIdentifierPart(c); } @Contract(pure = true) public static boolean isJavaIdentifier(@NotNull String text) { int len = text.length(); if (len == 0) return false; if (!isJavaIdentifierStart(text.charAt(0))) return false; for (int i = 1; i < len; i++) { if (!isJavaIdentifierPart(text.charAt(i))) return false; } return true; } /** * Escape property name or key in property file. Unicode characters are escaped as well. * * @param input an input to escape * @param isKey if true, the rules for key escaping are applied. The leading space is escaped in that case. * @return an escaped string */ @NotNull @Contract(pure = true) public static String escapeProperty(@NotNull String input, final boolean isKey) { final StringBuilder escaped = new StringBuilder(input.length()); for (int i = 0; i < input.length(); i++) { final char ch = input.charAt(i); switch (ch) { case ' ': if (isKey && i == 0) { // only the leading space has to be escaped escaped.append('\\'); } escaped.append(' '); break; case '\t': escaped.append("\\t"); break; case '\r': escaped.append("\\r"); break; case '\n': escaped.append("\\n"); break; case '\f': escaped.append("\\f"); break; case '\\': case '#': case '!': case ':': case '=': escaped.append('\\'); escaped.append(ch); break; default: if (20 < ch && ch < 0x7F) { escaped.append(ch); } else { escaped.append("\\u"); escaped.append(Character.forDigit((ch >> 12) & 0xF, 16)); escaped.append(Character.forDigit((ch >> 8) & 0xF, 16)); escaped.append(Character.forDigit((ch >> 4) & 0xF, 16)); escaped.append(Character.forDigit((ch) & 0xF, 16)); } break; } } return escaped.toString(); } @NotNull @Contract(pure = true) public static String getQualifiedName(@Nullable String packageName, @NotNull String className) { if (packageName == null || packageName.isEmpty()) { return className; } return packageName + '.' + className; } @Contract(pure = true) public static int compareVersionNumbers(@Nullable String v1, @Nullable String v2) { // todo duplicates com.intellij.util.text.VersionComparatorUtil.compare // todo please refactor next time you make changes here if (v1 == null && v2 == null) { return 0; } if (v1 == null) { return -1; } if (v2 == null) { return 1; } String[] part1 = v1.split("[._\\-]"); String[] part2 = v2.split("[._\\-]"); int idx = 0; for (; idx < part1.length && idx < part2.length; idx++) { String p1 = part1[idx]; String p2 = part2[idx]; int cmp; if (p1.matches("\\d+") && p2.matches("\\d+")) { cmp = new Integer(p1).compareTo(new Integer(p2)); } else { cmp = part1[idx].compareTo(part2[idx]); } if (cmp != 0) return cmp; } if (part1.length != part2.length) { boolean left = part1.length > idx; String[] parts = left ? part1 : part2; for (; idx < parts.length; idx++) { String p = parts[idx]; int cmp; if (p.matches("\\d+")) { cmp = new Integer(p).compareTo(0); } else { cmp = 1; } if (cmp != 0) return left ? cmp : -cmp; } } return 0; } @Contract(pure = true) public static int getOccurrenceCount(@NotNull String text, final char c) { int res = 0; int i = 0; while (i < text.length()) { i = text.indexOf(c, i); if (i >= 0) { res++; i++; } else { break; } } return res; } @Contract(pure = true) public static int getOccurrenceCount(@NotNull String text, @NotNull String s) { int res = 0; int i = 0; while (i < text.length()) { i = text.indexOf(s, i); if (i >= 0) { res++; i++; } else { break; } } return res; } @Contract(pure = true) public static int getIgnoreCaseOccurrenceCount(@NotNull String text, @NotNull String s) { int res = 0; int i = 0; while (i < text.length()) { i = indexOfIgnoreCase(text, s, i); if (i >= 0) { res++; i++; } else { break; } } return res; } @NotNull @Contract(pure = true) public static String fixVariableNameDerivedFromPropertyName(@NotNull String name) { if (isEmptyOrSpaces(name)) return name; char c = name.charAt(0); if (isVowel(c)) { return "an" + Character.toUpperCase(c) + name.substring(1); } return "a" + Character.toUpperCase(c) + name.substring(1); } @NotNull @Contract(pure = true) public static String sanitizeJavaIdentifier(@NotNull String name) { final StringBuilder result = new StringBuilder(name.length()); for (int i = 0; i < name.length(); i++) { final char ch = name.charAt(i); if (Character.isJavaIdentifierPart(ch)) { if (result.length() == 0 && !Character.isJavaIdentifierStart(ch)) { result.append("_"); } result.append(ch); } } return result.toString(); } public static void assertValidSeparators(@NotNull CharSequence s) { char[] chars = CharArrayUtil.fromSequenceWithoutCopying(s); int slashRIndex = -1; if (chars != null) { for (int i = 0, len = s.length(); i < len; ++i) { if (chars[i] == '\r') { slashRIndex = i; break; } } } else { for (int i = 0, len = s.length(); i < len; i++) { if (s.charAt(i) == '\r') { slashRIndex = i; break; } } } if (slashRIndex != -1) { String context = String.valueOf(last(s.subSequence(0, slashRIndex), 10, true)) + first(s.subSequence(slashRIndex, s.length()), 10, true); context = escapeStringCharacters(context); throw new AssertionError("Wrong line separators: '" + context + "' at offset " + slashRIndex); } } @NotNull @Contract(pure = true) public static String tail(@NotNull String s, final int idx) { return idx >= s.length() ? "" : s.substring(idx); } /** * Splits string by lines. * * @param string String to split * @return array of strings */ @NotNull @Contract(pure = true) public static String[] splitByLines(@NotNull String string) { return splitByLines(string, true); } /** * Splits string by lines. If several line separators are in a row corresponding empty lines * are also added to result if {@code excludeEmptyStrings} is {@code false}. * * @param string String to split * @return array of strings */ @NotNull @Contract(pure = true) public static String[] splitByLines(@NotNull String string, boolean excludeEmptyStrings) { return (excludeEmptyStrings ? EOL_SPLIT_PATTERN : EOL_SPLIT_PATTERN_WITH_EMPTY).split(string); } @NotNull @Contract(pure = true) public static String[] splitByLinesDontTrim(@NotNull String string) { return EOL_SPLIT_DONT_TRIM_PATTERN.split(string); } /** * Splits string by lines, keeping all line separators at the line ends and in the empty lines. *
E.g. splitting text *
* foo\r\n
* \n
* bar\n
* \r\n
* baz\r
* \r
*
* will return the following array: foo\r\n, \n, bar\n, \r\n, baz\r, \r * */ @NotNull @Contract(pure = true) public static String[] splitByLinesKeepSeparators(@NotNull String string) { return EOL_SPLIT_KEEP_SEPARATORS.split(string); } @NotNull @Contract(pure = true) public static List> getWordsWithOffset(@NotNull String s) { List> res = ContainerUtil.newArrayList(); s += " "; StringBuilder name = new StringBuilder(); int startInd = -1; for (int i = 0; i < s.length(); i++) { if (Character.isWhitespace(s.charAt(i))) { if (name.length() > 0) { res.add(Pair.create(name.toString(), startInd)); name.setLength(0); startInd = -1; } } else { if (startInd == -1) { startInd = i; } name.append(s.charAt(i)); } } return res; } @Contract(pure = true) public static int naturalCompare(@Nullable String string1, @Nullable String string2) { return NaturalComparator.INSTANCE.compare(string1, string2); } @Contract(pure = true) public static boolean isDecimalDigit(char c) { return c >= '0' && c <= '9'; } @Contract("null -> false") public static boolean isNotNegativeNumber(@Nullable CharSequence s) { if (s == null) { return false; } for (int i = 0; i < s.length(); i++) { if (!isDecimalDigit(s.charAt(i))) { return false; } } return true; } @Contract(pure = true) public static int compare(@Nullable String s1, @Nullable String s2, boolean ignoreCase) { //noinspection StringEquality if (s1 == s2) return 0; if (s1 == null) return -1; if (s2 == null) return 1; return ignoreCase ? s1.compareToIgnoreCase(s2) : s1.compareTo(s2); } @Contract(pure = true) public static int comparePairs(@Nullable String s1, @Nullable String t1, @Nullable String s2, @Nullable String t2, boolean ignoreCase) { final int compare = compare(s1, s2, ignoreCase); return compare != 0 ? compare : compare(t1, t2, ignoreCase); } @Contract(pure = true) public static int hashCode(@NotNull CharSequence s) { return stringHashCode(s); } @Contract(pure = true) public static boolean equals(@Nullable CharSequence s1, @Nullable CharSequence s2) { if (s1 == null ^ s2 == null) { return false; } if (s1 == null) { return true; } if (s1.length() != s2.length()) { return false; } for (int i = 0; i < s1.length(); i++) { if (s1.charAt(i) != s2.charAt(i)) { return false; } } return true; } @Contract(pure = true) public static boolean equalsIgnoreCase(@Nullable CharSequence s1, @Nullable CharSequence s2) { if (s1 == null ^ s2 == null) { return false; } if (s1 == null) { return true; } if (s1.length() != s2.length()) { return false; } for (int i = 0; i < s1.length(); i++) { if (!charsEqualIgnoreCase(s1.charAt(i), s2.charAt(i))) { return false; } } return true; } @Contract(pure = true) public static boolean equalsIgnoreWhitespaces(@Nullable CharSequence s1, @Nullable CharSequence s2) { if (s1 == null ^ s2 == null) { return false; } if (s1 == null) { return true; } int len1 = s1.length(); int len2 = s2.length(); int index1 = 0; int index2 = 0; while (index1 < len1 && index2 < len2) { if (s1.charAt(index1) == s2.charAt(index2)) { index1++; index2++; continue; } boolean skipped = false; while (index1 != len1 && isWhiteSpace(s1.charAt(index1))) { skipped = true; index1++; } while (index2 != len2 && isWhiteSpace(s2.charAt(index2))) { skipped = true; index2++; } if (!skipped) return false; } for (; index1 != len1; index1++) { if (!isWhiteSpace(s1.charAt(index1))) return false; } for (; index2 != len2; index2++) { if (!isWhiteSpace(s2.charAt(index2))) return false; } return true; } @Contract(pure = true) public static boolean equalsTrimWhitespaces(@NotNull CharSequence s1, @NotNull CharSequence s2) { int start1 = 0; int end1 = s1.length(); int end2 = s2.length(); while (start1 < end1) { char c = s1.charAt(start1); if (!isWhiteSpace(c)) break; start1++; } while (start1 < end1) { char c = s1.charAt(end1 - 1); if (!isWhiteSpace(c)) break; end1--; } int start2 = 0; while (start2 < end2) { char c = s2.charAt(start2); if (!isWhiteSpace(c)) break; start2++; } while (start2 < end2) { char c = s2.charAt(end2 - 1); if (!isWhiteSpace(c)) break; end2--; } CharSequence ts1 = new CharSequenceSubSequence(s1, start1, end1); CharSequence ts2 = new CharSequenceSubSequence(s2, start2, end2); return equals(ts1, ts2); } /** * Collapses all white-space (including new lines) between non-white-space characters to a single space character. * Leading and trailing white space is removed. */ public static String collapseWhiteSpace(@NotNull CharSequence s) { final StringBuilder result = new StringBuilder(); boolean space = false; for (int i = 0, length = s.length(); i < length; i++) { final char ch = s.charAt(i); if (isWhiteSpace(ch)) { if (!space) space = true; } else { if (space && result.length() > 0) result.append(' '); result.append(ch); space = false; } } return result.toString(); } @Contract(pure = true) public static boolean findIgnoreCase(@Nullable String toFind, @NotNull String... where) { for (String string : where) { if (equalsIgnoreCase(toFind, string)) return true; } return false; } @Contract(pure = true) public static int compare(char c1, char c2, boolean ignoreCase) { // duplicating String.equalsIgnoreCase logic int d = c1 - c2; if (d == 0 || !ignoreCase) { return d; } // If characters don't match but case may be ignored, // try converting both characters to uppercase. // If the results match, then the comparison scan should // continue. char u1 = StringUtilRt.toUpperCase(c1); char u2 = StringUtilRt.toUpperCase(c2); d = u1 - u2; if (d != 0) { // Unfortunately, conversion to uppercase does not work properly // for the Georgian alphabet, which has strange rules about case // conversion. So we need to make one last check before // exiting. d = StringUtilRt.toLowerCase(u1) - StringUtilRt.toLowerCase(u2); } return d; } @Contract(pure = true) public static boolean charsMatch(char c1, char c2, boolean ignoreCase) { return compare(c1, c2, ignoreCase) == 0; } @NotNull @Contract(pure = true) public static String formatLinks(@NotNull String message) { Pattern linkPattern = Pattern.compile("http://[a-zA-Z0-9./\\-+]+"); StringBuffer result = new StringBuffer(); Matcher m = linkPattern.matcher(message); while (m.find()) { m.appendReplacement(result, "" + m.group() + ""); } m.appendTail(result); return result.toString(); } @Contract(pure = true) public static boolean isHexDigit(char c) { return '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F'; } @Contract(pure = true) public static boolean isOctalDigit(char c) { return '0' <= c && c <= '7'; } @NotNull @Contract(pure = true) public static String shortenTextWithEllipsis(@NotNull final String text, final int maxLength, final int suffixLength) { return shortenTextWithEllipsis(text, maxLength, suffixLength, false); } @NotNull @Contract(pure = true) public static String trimMiddle(@NotNull String text, int maxLength) { return shortenTextWithEllipsis(text, maxLength, maxLength >> 1, true); } @NotNull @Contract(pure = true) public static String shortenTextWithEllipsis(@NotNull final String text, final int maxLength, final int suffixLength, @NotNull String symbol) { final int textLength = text.length(); if (textLength > maxLength) { final int prefixLength = maxLength - suffixLength - symbol.length(); assert prefixLength > 0; return text.substring(0, prefixLength) + symbol + text.substring(textLength - suffixLength); } else { return text; } } @NotNull @Contract(pure = true) public static String shortenTextWithEllipsis(@NotNull final String text, final int maxLength, final int suffixLength, boolean useEllipsisSymbol) { String symbol = useEllipsisSymbol ? "\u2026" : "..."; return shortenTextWithEllipsis(text, maxLength, suffixLength, symbol); } @NotNull @Contract(pure = true) public static String shortenPathWithEllipsis(@NotNull final String path, final int maxLength, boolean useEllipsisSymbol) { return shortenTextWithEllipsis(path, maxLength, (int)(maxLength * 0.7), useEllipsisSymbol); } @NotNull @Contract(pure = true) public static String shortenPathWithEllipsis(@NotNull final String path, final int maxLength) { return shortenPathWithEllipsis(path, maxLength, false); } @Contract(pure = true) public static boolean charsEqualIgnoreCase(char a, char b) { return charsMatch(a, b, true); } @Contract(pure = true) public static char toUpperCase(char a) { return StringUtilRt.toUpperCase(a); } @Contract(value = "null -> null; !null -> !null", pure = true) public static String toUpperCase(String a) { if (a == null) return null; StringBuilder answer = null; for (int i = 0; i < a.length(); i++) { char c = a.charAt(i); char upCased = toUpperCase(c); if (answer == null && upCased != c) { answer = new StringBuilder(a.length()); answer.append(a.subSequence(0, i)); } if (answer != null) { answer.append(upCased); } } return answer == null ? a : answer.toString(); } @Contract(pure = true) public static char toLowerCase(final char a) { return StringUtilRt.toLowerCase(a); } @Contract(pure = true) public static boolean isUpperCase(@NotNull CharSequence sequence) { for (int i = 0; i < sequence.length(); i++) { if (!Character.isUpperCase(sequence.charAt(i))) return false; } return true; } @Nullable public static LineSeparator detectSeparators(@NotNull CharSequence text) { int index = indexOfAny(text, "\n\r"); if (index == -1) return null; LineSeparator lineSeparator = getLineSeparatorAt(text, index); if (lineSeparator == null) { throw new AssertionError(); } return lineSeparator; } @Nullable public static LineSeparator getLineSeparatorAt(@NotNull CharSequence text, int index) { if (index < 0 || index >= text.length()) { return null; } char ch = text.charAt(index); if (ch == '\r') { return index + 1 < text.length() && text.charAt(index + 1) == '\n' ? LineSeparator.CRLF : LineSeparator.CR; } return ch == '\n' ? LineSeparator.LF : null; } @NotNull @Contract(pure = true) public static String convertLineSeparators(@NotNull String text) { return StringUtilRt.convertLineSeparators(text); } @NotNull @Contract(pure = true) public static String convertLineSeparators(@NotNull String text, boolean keepCarriageReturn) { return StringUtilRt.convertLineSeparators(text, keepCarriageReturn); } @NotNull @Contract(pure = true) public static String convertLineSeparators(@NotNull String text, @NotNull String newSeparator) { return StringUtilRt.convertLineSeparators(text, newSeparator); } @NotNull public static String convertLineSeparators(@NotNull String text, @NotNull String newSeparator, @Nullable int[] offsetsToKeep) { return StringUtilRt.convertLineSeparators(text, newSeparator, offsetsToKeep); } @Contract(pure = true) public static int parseInt(@Nullable String string, int defaultValue) { return StringUtilRt.parseInt(string, defaultValue); } @NotNull @Contract(pure = true) public static String getShortName(@NotNull String fqName) { return StringUtilRt.getShortName(fqName); } @NotNull @Contract(pure = true) public static String getShortName(@NotNull String fqName, char separator) { return StringUtilRt.getShortName(fqName, separator); } /** * Equivalent for {@code getShortName(fqName).equals(shortName)}, but could be faster. * * @param fqName fully-qualified name (dot-separated) * @param shortName a short name, must not contain dots * @return true if specified short name is a short name of fully-qualified name */ public static boolean isShortNameOf(@NotNull String fqName, @NotNull String shortName) { if (fqName.length() < shortName.length()) return false; if (fqName.length() == shortName.length()) return fqName.equals(shortName); int diff = fqName.length() - shortName.length(); if (fqName.charAt(diff - 1) != '.') return false; return fqName.regionMatches(diff, shortName, 0, shortName.length()); } /** * Strips class name from Object#toString if present. * To be used as custom data type renderer for java.lang.Object. * To activate just add {@code StringUtil.toShortString(this)} * expression in Settings | Debugger | Data Views. */ @Contract("null->null;!null->!null") @SuppressWarnings("UnusedDeclaration") static String toShortString(@Nullable Object o) { if (o == null) return null; if (o instanceof CharSequence) return o.toString(); String className = o.getClass().getName(); String s = o.toString(); if (!s.startsWith(className)) return s; return s.length() > className.length() && !Character.isLetter(s.charAt(className.length())) ? trimStart(s, className) : s; } @NotNull @Contract(pure = true) public static CharSequence newBombedCharSequence(@NotNull CharSequence sequence, long delay) { final long myTime = System.currentTimeMillis() + delay; return new BombedCharSequence(sequence) { @Override protected void checkCanceled() { long l = System.currentTimeMillis(); if (l >= myTime) { throw new ProcessCanceledException(); } } }; } public static boolean trimEnd(@NotNull StringBuilder buffer, @NotNull CharSequence end) { if (endsWith(buffer, end)) { buffer.delete(buffer.length() - end.length(), buffer.length()); return true; } return false; } /** * Say smallPart = "op" and bigPart="open". Method returns true for "Ope" and false for "ops" */ @Contract(pure = true) @SuppressWarnings("StringToUpperCaseOrToLowerCaseWithoutLocale") public static boolean isBetween(@NotNull String string, @NotNull String smallPart, @NotNull String bigPart) { final String s = string.toLowerCase(); return s.startsWith(smallPart.toLowerCase()) && bigPart.toLowerCase().startsWith(s); } /** * Does the string have an uppercase character? * @param s the string to test. * @return true if the string has an uppercase character, false if not. */ public static boolean hasUpperCaseChar(String s) { char[] chars = s.toCharArray(); for (char c : chars) { if (Character.isUpperCase(c)) { return true; } } return false; } /** * Does the string have a lowercase character? * @param s the string to test. * @return true if the string has a lowercase character, false if not. */ public static boolean hasLowerCaseChar(String s) { char[] chars = s.toCharArray(); for (char c : chars) { if (Character.isLowerCase(c)) { return true; } } return false; } private static final Pattern UNICODE_CHAR = Pattern.compile("\\\\u[0-9a-fA-F]{4}"); public static String replaceUnicodeEscapeSequences(String text) { if (text == null) return null; final Matcher matcher = UNICODE_CHAR.matcher(text); if (!matcher.find()) return text; // fast path matcher.reset(); int lastEnd = 0; final StringBuilder sb = new StringBuilder(text.length()); while (matcher.find()) { sb.append(text, lastEnd, matcher.start()); final char c = (char)Integer.parseInt(matcher.group().substring(2), 16); sb.append(c); lastEnd = matcher.end(); } sb.append(text.substring(lastEnd)); return sb.toString(); } /** * Expirable CharSequence. Very useful to control external library execution time, * i.e. when java.util.regex.Pattern match goes out of control. */ public abstract static class BombedCharSequence implements CharSequence { private final CharSequence delegate; private int i; private boolean myDefused; public BombedCharSequence(@NotNull CharSequence sequence) { delegate = sequence; } @Override public int length() { check(); return delegate.length(); } @Override public char charAt(int i) { check(); return delegate.charAt(i); } protected void check() { if (myDefused) { return; } if ((++i & 1023) == 0) { checkCanceled(); } } public final void defuse() { myDefused = true; } @NotNull @Override public String toString() { check(); return delegate.toString(); } protected abstract void checkCanceled(); @NotNull @Override public CharSequence subSequence(int i, int i1) { check(); return delegate.subSequence(i, i1); } } @Contract(pure = true) @NotNull public static String toHexString(@NotNull byte[] bytes) { @SuppressWarnings("SpellCheckingInspection") String digits = "0123456789abcdef"; StringBuilder sb = new StringBuilder(2 * bytes.length); for (byte b : bytes) sb.append(digits.charAt((b >> 4) & 0xf)).append(digits.charAt(b & 0xf)); return sb.toString(); } @Contract(pure = true) @NotNull public static byte[] parseHexString(@NotNull String str) { int len = str.length(); if (len % 2 != 0) throw new IllegalArgumentException("Non-even-length: " + str); byte[] bytes = new byte[len / 2]; for (int i = 0; i < len; i += 2) { bytes[i / 2] = (byte)((Character.digit(str.charAt(i), 16) << 4) + Character.digit(str.charAt(i + 1), 16)); } return bytes; } /** @deprecated use {@link #startsWithConcatenation(String, String...)} (to remove in IDEA 15) */ @Deprecated public static boolean startsWithConcatenationOf(@NotNull String string, @NotNull String firstPrefix, @NotNull String secondPrefix) { return startsWithConcatenation(string, firstPrefix, secondPrefix); } /** * @return {@code true} if the passed string is not {@code null} and not empty * and contains only latin upper- or lower-case characters and digits; {@code false} otherwise. */ @Contract(pure = true) public static boolean isLatinAlphanumeric(@Nullable CharSequence str) { if (isEmpty(str)) { return false; } for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); if (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z' || Character.isDigit(c)) { continue; } return false; } return true; } } ================================================ FILE: kotlin-bundled-compiler/src/com/intellij/util/SequentialModalProgressTask.java ================================================ package com.intellij.util; import java.lang.reflect.InvocationTargetException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.Task; import com.intellij.openapi.project.Project; public class SequentialModalProgressTask extends Task.Modal { private static final Logger LOG = Logger.getInstance("#" + SequentialModalProgressTask.class.getName()); private static final long DEFAULT_MIN_ITERATION_MIN_TIME = 500; /** * We want to perform the task by big chunks at EDT. However, there is a * possible case that particular task iteration is executed in short amount * of time. Hence, we may want to execute more than one chunk during single * EDT iteration. This field holds min amount of time (in milliseconds) to * spend to performing the task. */ private long myMinIterationTime = DEFAULT_MIN_ITERATION_MIN_TIME; private final String myTitle; private ProgressIndicator myIndicator; private SequentialTask myTask; public SequentialModalProgressTask(@Nullable Project project, @NotNull String title) { this(project, title, true); } public SequentialModalProgressTask(@Nullable Project project, @NotNull String title, boolean canBeCancelled) { super(project, title, canBeCancelled); myTitle = title; } @Override public void run(@NotNull ProgressIndicator indicator) { try { doRun(indicator); } catch (Exception e) { LOG.info("Unexpected exception occurred during processing sequential task '" + myTitle + "'", e); } finally { indicator.stop(); } } public void doRun(@NotNull ProgressIndicator indicator) throws InvocationTargetException, InterruptedException { final SequentialTask task = myTask; if (task == null) { return; } myIndicator = indicator; prepare(task); // We need to sync background thread and EDT here in order to avoid // situation when event queue is full of processing requests. while (!task.isDone()) { if (indicator.isCanceled()) { task.stop(); break; } long start = System.currentTimeMillis(); try { while (!task.isDone() && System.currentTimeMillis() - start < myMinIterationTime) { task.iteration(); } } catch (RuntimeException e) { task.stop(); throw e; } } } public void setMinIterationTime(long minIterationTime) { myMinIterationTime = minIterationTime; } public void setTask(@Nullable SequentialTask task) { myTask = task; } public ProgressIndicator getIndicator() { return myIndicator; } /** * Executes preliminary jobs prior to the target sequential task processing * ({@link SequentialTask#prepare()} by default). * * @param task * task to be executed */ protected void prepare(@NotNull SequentialTask task) { task.prepare(); } } ================================================ FILE: kotlin-bundled-compiler/src/com/intellij/util/SequentialTask.java ================================================ package com.intellij.util; public interface SequentialTask { /** * Callback method that is assumed to be called before the processing. */ void prepare(); /** * @return true if the processing is complete; * false otherwise */ boolean isDone(); /** * Asks current task to perform one more processing iteration. * * @return true if the processing is done; false * otherwise */ boolean iteration(); /** * Asks current task to stop the processing (if any). */ void stop(); } ================================================ FILE: kotlin-bundled-compiler/src/com/intellij/util/SingletonSet.java ================================================ /* * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.intellij.util; import com.intellij.util.containers.SingletonIterator; import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NotNull; import java.util.Collection; import java.util.Iterator; import java.util.Set; /** * Read-only set consisting of the only element */ public class SingletonSet implements Set { private final E theElement; public SingletonSet(E e) { theElement = e; } @Override public int size() { return 1; } @Override public boolean contains(Object elem) { //noinspection unchecked return getStrategy().equals(theElement, (E)elem); } @NotNull @Override public Iterator iterator() { return new SingletonIterator<>(theElement); } @NotNull @Override public Object[] toArray() { return new Object[]{theElement}; } @NotNull @Override public T[] toArray(@NotNull T[] a) { if (a.length == 0) { a = ArrayUtil.newArray(ArrayUtil.getComponentType(a), 1); } //noinspection unchecked a[0] = (T)theElement; if (a.length > 1) { a[1] = null; } return a; } @Override public boolean add(E t) { throw new IncorrectOperationException(); } @Override public boolean remove(Object o) { throw new IncorrectOperationException(); } @Override public boolean containsAll(@NotNull Collection c) { for (Object e : c) { if (!contains(e)) { return false; } } return true; } @Override public boolean addAll(@NotNull Collection c) { throw new IncorrectOperationException(); } @Override public boolean retainAll(@NotNull Collection c) { throw new IncorrectOperationException(); } @Override public boolean removeAll(@NotNull Collection c) { throw new IncorrectOperationException(); } @Override public void clear() { throw new IncorrectOperationException(); } @Override public boolean isEmpty() { return false; } @NotNull protected TObjectHashingStrategy getStrategy() { //noinspection unchecked return TObjectHashingStrategy.CANONICAL; } @NotNull public static Set withCustomStrategy(T o, @NotNull TObjectHashingStrategy strategy) { return new CustomStrategySingletonSet<>(o, strategy); } private static class CustomStrategySingletonSet extends SingletonSet { @NotNull private final TObjectHashingStrategy strategy; private CustomStrategySingletonSet(E e, @NotNull final TObjectHashingStrategy strategy) { super(e); this.strategy = strategy; } @Override @NotNull protected TObjectHashingStrategy getStrategy() { return strategy; } } } ================================================ FILE: kotlin-bundled-compiler/src/com/intellij/util/containers/LinkedMultiMap.java ================================================ package com.intellij.util.containers; @Deprecated public class LinkedMultiMap extends MultiMap { } ================================================ FILE: kotlin-bundled-compiler/src/com/intellij/util/containers/MultiMap.java ================================================ // Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.util.containers; import com.intellij.util.SmartList; import gnu.trove.THashMap; import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.Serializable; import java.util.HashMap; import java.util.*; import java.util.concurrent.ConcurrentHashMap; /** * Consider to use factory methods {@link #createLinked()}, {@link #createSet()}, {@link #createSmart()}, {@link #create(TObjectHashingStrategy)} instead of override. * @see BidirectionalMultiMap * @see ConcurrentMultiMap * @author Dmitry Avdeev */ public class MultiMap implements Serializable { public static final MultiMap EMPTY = new EmptyMap(); private static final long serialVersionUID = -2632269270151455493L; protected final Map> myMap; private Collection values; public MultiMap() { myMap = createMap(); } public MultiMap(@NotNull Map> mapImpl) { myMap = mapImpl; } public MultiMap(@NotNull MultiMap toCopy) { this(); putAllValues(toCopy); } @NotNull public MultiMap copy() { return new MultiMap<>(this); } public MultiMap(int initialCapacity, float loadFactor) { myMap = createMap(initialCapacity, loadFactor); } @NotNull protected Map> createMap() { return new java.util.HashMap>(); } @NotNull protected Map> createMap(int initialCapacity, float loadFactor) { return new HashMap>(initialCapacity, loadFactor); } @NotNull protected Collection createCollection() { return new SmartList(); } @NotNull protected Collection createEmptyCollection() { return Collections.emptyList(); } public void putAllValues(@NotNull MultiMap from) { for (Map.Entry> entry : from.entrySet()) { putValues(entry.getKey(), entry.getValue()); } } public void putAllValues(@NotNull Map from) { for (Map.Entry entry : from.entrySet()) { putValue(entry.getKey(), entry.getValue()); } } public void putValues(K key, @NotNull Collection values) { Collection list = myMap.get(key); if (list == null) { list = createCollection(); myMap.put(key, list); } list.addAll(values); } public void putValue(@Nullable K key, V value) { Collection list = myMap.get(key); if (list == null) { list = createCollection(); myMap.put(key, list); } list.add(value); } @NotNull public Set>> entrySet() { return myMap.entrySet(); } public boolean isEmpty() { if (myMap.isEmpty()) return true; for(Collection valueList: myMap.values()) { if (!valueList.isEmpty()) { return false; } } return true; } public boolean containsKey(K key) { return myMap.containsKey(key); } public boolean containsScalarValue(V value) { for(Collection valueList: myMap.values()) { if (valueList.contains(value)) { return true; } } return false; } @NotNull public Collection get(final K key) { final Collection collection = myMap.get(key); return collection == null ? createEmptyCollection() : collection; } @NotNull public Collection getModifiable(final K key) { Collection collection = myMap.get(key); if (collection == null) { myMap.put(key, collection = createCollection()); } return collection; } @NotNull public Set keySet() { return myMap.keySet(); } public int size() { return myMap.size(); } public void put(final K key, Collection values) { myMap.put(key, values); } /** * @deprecated use {@link #remove(Object, Object)} instead */ @Deprecated public void removeValue(K key, V value) { remove(key, value); } public boolean remove(final K key, final V value) { final Collection values = myMap.get(key); if (values != null) { boolean removed = values.remove(value); if (values.isEmpty()) { myMap.remove(key); } return removed; } return false; } @NotNull public Collection values() { if (values == null) { values = new AbstractCollection() { @NotNull @Override public Iterator iterator() { return new Iterator() { private final Iterator> mapIterator = myMap.values().iterator(); private Iterator itr = EmptyIterator.getInstance(); @Override public boolean hasNext() { do { if (itr.hasNext()) return true; if (!mapIterator.hasNext()) return false; itr = mapIterator.next().iterator(); } while (true); } @Override public V next() { do { if (itr.hasNext()) return itr.next(); if (!mapIterator.hasNext()) throw new NoSuchElementException(); itr = mapIterator.next().iterator(); } while (true); } @Override public void remove() { itr.remove(); } }; } @Override public int size() { int res = 0; for (Collection vs : myMap.values()) { res += vs.size(); } return res; } // Don't remove this method!!! @Override public boolean contains(Object o) { for (Collection vs : myMap.values()) { if (vs.contains(o)) return true; } return false; } }; } return values; } public void clear() { myMap.clear(); } @Nullable public Collection remove(K key) { return myMap.remove(key); } @NotNull public static MultiMap emptyInstance() { @SuppressWarnings("unchecked") final MultiMap empty = EMPTY; return empty; } /** * Null keys supported. */ @NotNull public static MultiMap create() { return new MultiMap(); } @NotNull public static MultiMap create(@NotNull final TObjectHashingStrategy strategy) { return new MultiMap() { @NotNull @Override protected Map> createMap() { return new THashMap>(strategy); } }; } @NotNull public static MultiMap createLinked() { return new LinkedMultiMap(); } @NotNull public static MultiMap createLinkedSet() { return new LinkedMultiMap() { @NotNull @Override protected Collection createCollection() { return new LinkedHashSet(); } @NotNull @Override protected Collection createEmptyCollection() { return Collections.emptySet(); } }; } @NotNull public static MultiMap createOrderedSet() { return new LinkedMultiMap() { @NotNull @Override protected Collection createCollection() { return new OrderedSet(); } @NotNull @Override protected Collection createEmptyCollection() { return Collections.emptySet(); } }; } @NotNull public static MultiMap createSmart() { return new MultiMap() { @NotNull @Override protected Map> createMap() { return new THashMap>(); } }; } @NotNull public static MultiMap createConcurrent() { return new MultiMap(new ConcurrentHashMap<>()) { @NotNull protected Collection createCollection() { return ContainerUtil.createLockFreeCopyOnWriteList(); } }; } @NotNull public static MultiMap createConcurrentSet() { return new ConcurrentMultiMap() { @NotNull @Override protected Collection createCollection() { return Collections.newSetFromMap(new ConcurrentHashMap<>()); } @NotNull @Override protected Collection createEmptyCollection() { return Collections.emptySet(); } }; } @NotNull public static MultiMap createSet() { return createSet(ContainerUtil.canonicalStrategy()); } @NotNull public static MultiMap createSet(@NotNull final TObjectHashingStrategy strategy) { return new MultiMap() { @NotNull @Override protected Collection createCollection() { return new SmartHashSet(); } @NotNull @Override protected Collection createEmptyCollection() { return Collections.emptySet(); } @NotNull @Override protected Map> createMap() { return new THashMap>(strategy); } }; } @NotNull public static MultiMap createWeakKey() { return new MultiMap() { @NotNull @Override protected Map> createMap() { return ContainerUtil.createWeakMap(); } }; } public static MultiMap create(int initialCapacity, float loadFactor) { return new MultiMap(initialCapacity, loadFactor); } @Override public boolean equals(Object o) { return this == o || o instanceof MultiMap && myMap.equals(((MultiMap)o).myMap); } @Override public int hashCode() { return myMap.hashCode(); } @Override public String toString() { return new java.util.HashMap>(myMap).toString(); } /** * @return immutable empty multi-map */ public static MultiMap empty() { //noinspection unchecked return EMPTY; } private static class EmptyMap extends MultiMap { @NotNull @Override protected Map createMap() { return Collections.emptyMap(); } @Override public void putValues(Object key, @NotNull Collection values) { throw new UnsupportedOperationException(); } @Override public void putValue(@Nullable Object key, Object value) { throw new UnsupportedOperationException(); } @Override public void put(Object key, Collection values) { throw new UnsupportedOperationException(); } @Override public boolean remove(Object key, Object value) { throw new UnsupportedOperationException(); } @Override public void clear() { throw new UnsupportedOperationException(); } @Nullable @Override public Collection remove(Object key) { throw new UnsupportedOperationException(); } } } ================================================ FILE: kotlin-bundled-compiler/src/com/intellij/util/containers/ObjectIntHashMap.java ================================================ package com.intellij.util.containers; import gnu.trove.TObjectHashingStrategy; import gnu.trove.TObjectIntHashMap; import org.jetbrains.annotations.NotNull; import java.util.Arrays; import java.util.Collections; import java.util.Set; public class ObjectIntHashMap extends TObjectIntHashMap implements ObjectIntMap { public ObjectIntHashMap(int initialCapacity) { super(initialCapacity); } public ObjectIntHashMap(@NotNull TObjectHashingStrategy strategy) { super(strategy); } public ObjectIntHashMap(int initialCapacity, @NotNull TObjectHashingStrategy strategy) { super(initialCapacity, strategy); } public ObjectIntHashMap() { super(); } public final int get(@NotNull K key) { return this.get(key, -1); } @Override public @NotNull Set keySet() { return Collections.emptySet(); } @NotNull @Override public int[] values() { return Arrays.copyOf(_values, _values.length); } @Override public @NotNull Iterable> entries() { return Collections.emptySet(); } public final int get(K key, int defaultValue) { int index = this.index(key); return index < 0 ? defaultValue : this._values[index]; } public int put(K key, int value, int defaultValue) { int index = this.index(key); int prev = super.put(key, value); return index >= 0 ? prev : defaultValue; } } ================================================ FILE: kotlin-bundled-compiler/src/it/unimi/dsi/fastutil/ints/IntOpenHashSet.java ================================================ package it.unimi.dsi.fastutil.ints; import it.unimi.dsi.fastutil.Hash; import it.unimi.dsi.fastutil.HashCommon; import java.io.Serializable; import java.util.Arrays; import java.util.Collection; import java.util.NoSuchElementException; public class IntOpenHashSet extends AbstractIntSet implements Hash, Serializable, Cloneable { private static final long serialVersionUID = 0L; protected transient int[] key; protected transient int mask; protected transient boolean containsNull; protected transient int n; protected transient int maxFill; protected final transient int minN; protected int size; protected final float f; public IntOpenHashSet(int expected, float f) { if (!(f <= 0.0F) && !(f >= 1.0F)) { if (expected < 0) { throw new IllegalArgumentException("The expected number of elements must be nonnegative"); } else { this.f = f; this.minN = this.n = HashCommon.arraySize(expected, f); this.mask = this.n - 1; this.maxFill = HashCommon.maxFill(this.n, f); this.key = new int[this.n + 1]; } } else { throw new IllegalArgumentException("Load factor must be greater than 0 and smaller than 1"); } } public IntOpenHashSet(int expected) { this(expected, 0.75F); } public IntOpenHashSet() { this(16, 0.75F); } private int realSize() { return this.containsNull ? this.size - 1 : this.size; } private void ensureCapacity(int capacity) { int needed = HashCommon.arraySize(capacity, this.f); if (needed > this.n) { this.rehash(needed); } } private void tryCapacity(long capacity) { int needed = (int)Math.min(1073741824L, Math.max(2L, HashCommon.nextPowerOfTwo((long)Math.ceil((double)((float)capacity / this.f))))); if (needed > this.n) { this.rehash(needed); } } public boolean addAll(Collection c) { if ((double)this.f <= 0.5D) { this.ensureCapacity(c.size()); } else { this.tryCapacity((long)(this.size() + c.size())); } return super.addAll(c); } public boolean add(int k) { if (k == 0) { if (this.containsNull) { return false; } this.containsNull = true; } else { int[] key = this.key; int pos; int curr; if ((curr = key[pos = HashCommon.mix(k) & this.mask]) != 0) { if (curr == k) { return false; } while((curr = key[pos = pos + 1 & this.mask]) != 0) { if (curr == k) { return false; } } } key[pos] = k; } if (this.size++ >= this.maxFill) { this.rehash(HashCommon.arraySize(this.size + 1, this.f)); } return true; } protected final void shiftKeys(int pos) { int[] key = this.key; while(true) { int last = pos; pos = pos + 1 & this.mask; int curr; while(true) { if ((curr = key[pos]) == 0) { key[last] = 0; return; } int slot = HashCommon.mix(curr) & this.mask; if (last <= pos) { if (last >= slot || slot > pos) { break; } } else if (last >= slot && slot > pos) { break; } pos = pos + 1 & this.mask; } key[last] = curr; } } private boolean removeEntry(int pos) { --this.size; this.shiftKeys(pos); if (this.n > this.minN && this.size < this.maxFill / 4 && this.n > 16) { this.rehash(this.n / 2); } return true; } private boolean removeNullEntry() { this.containsNull = false; this.key[this.n] = 0; --this.size; if (this.n > this.minN && this.size < this.maxFill / 4 && this.n > 16) { this.rehash(this.n / 2); } return true; } public boolean remove(int k) { if (k == 0) { return this.containsNull ? this.removeNullEntry() : false; } else { int[] key = this.key; int curr; int pos; if ((curr = key[pos = HashCommon.mix(k) & this.mask]) == 0) { return false; } else if (k == curr) { return this.removeEntry(pos); } else { while((curr = key[pos = pos + 1 & this.mask]) != 0) { if (k == curr) { return this.removeEntry(pos); } } return false; } } } public boolean contains(int k) { if (k == 0) { return this.containsNull; } else { int[] key = this.key; int curr; int pos; if ((curr = key[pos = HashCommon.mix(k) & this.mask]) == 0) { return false; } else if (k == curr) { return true; } else { while((curr = key[pos = pos + 1 & this.mask]) != 0) { if (k == curr) { return true; } } return false; } } } public void clear() { if (this.size != 0) { this.size = 0; this.containsNull = false; Arrays.fill(this.key, 0); } } public int size() { return this.size; } public boolean isEmpty() { return this.size == 0; } public IntIterator iterator() { return new IntOpenHashSet.SetIterator(); } protected void rehash(int newN) { int[] key = this.key; int mask = newN - 1; int[] newKey = new int[newN + 1]; int i = this.n; int pos; for(int var7 = this.realSize(); var7-- != 0; newKey[pos] = key[i]) { do { --i; } while(key[i] == 0); if (newKey[pos = HashCommon.mix(key[i]) & mask] != 0) { while(newKey[pos = pos + 1 & mask] != 0) { } } } this.n = newN; this.mask = mask; this.maxFill = HashCommon.maxFill(this.n, this.f); this.key = newKey; } public IntOpenHashSet clone() { IntOpenHashSet c; try { c = (IntOpenHashSet)super.clone(); } catch (CloneNotSupportedException var3) { throw new InternalError(); } c.key = (int[])this.key.clone(); c.containsNull = this.containsNull; return c; } public int hashCode() { int h = 0; int j = this.realSize(); for(int i = 0; j-- != 0; ++i) { while(this.key[i] == 0) { ++i; } h += this.key[i]; } return h; } private class SetIterator implements IntIterator { int pos; int last; int c; boolean mustReturnNull; IntArrayList wrapped; private SetIterator() { this.pos = IntOpenHashSet.this.n; this.last = -1; this.c = IntOpenHashSet.this.size; this.mustReturnNull = IntOpenHashSet.this.containsNull; } public boolean hasNext() { return this.c != 0; } public int nextInt() { if (!this.hasNext()) { throw new NoSuchElementException(); } else { --this.c; if (this.mustReturnNull) { this.mustReturnNull = false; this.last = IntOpenHashSet.this.n; return IntOpenHashSet.this.key[IntOpenHashSet.this.n]; } else { int[] key = IntOpenHashSet.this.key; while(--this.pos >= 0) { if (key[this.pos] != 0) { return key[this.last = this.pos]; } } this.last = -2147483648; return this.wrapped.getInt(-this.pos - 1); } } } private final void shiftKeys(int pos) { int[] key = IntOpenHashSet.this.key; while(true) { int last = pos; pos = pos + 1 & IntOpenHashSet.this.mask; int curr; while(true) { if ((curr = key[pos]) == 0) { key[last] = 0; return; } int slot = HashCommon.mix(curr) & IntOpenHashSet.this.mask; if (last <= pos) { if (last >= slot || slot > pos) { break; } } else if (last >= slot && slot > pos) { break; } pos = pos + 1 & IntOpenHashSet.this.mask; } if (pos < last) { if (this.wrapped == null) { this.wrapped = new IntArrayList(2); } this.wrapped.add(key[pos]); } key[last] = curr; } } public void remove() { if (this.last == -1) { throw new IllegalStateException(); } else { if (this.last == IntOpenHashSet.this.n) { IntOpenHashSet.this.containsNull = false; IntOpenHashSet.this.key[IntOpenHashSet.this.n] = 0; } else { if (this.pos < 0) { IntOpenHashSet.this.remove(this.wrapped.getInt(-this.pos - 1)); this.last = -1; return; } this.shiftKeys(this.last); } --IntOpenHashSet.this.size; this.last = -1; } } } } ================================================ FILE: kotlin-bundled-compiler/src/org/jetbrains/kotlin/idea/core/formatter/KotlinPackageEntry.kt ================================================ package org.jetbrains.kotlin.idea.core.formatter class KotlinPackageEntry( packageName: String, val withSubpackages: Boolean ) { val packageName = packageName.removeSuffix(".*") companion object { @JvmField val ALL_OTHER_IMPORTS_ENTRY = KotlinPackageEntry("import all other imports", withSubpackages = true) @JvmField val ALL_OTHER_ALIAS_IMPORTS_ENTRY = KotlinPackageEntry("", withSubpackages = true) } fun matchesPackageName(otherPackageName: String): Boolean { if (otherPackageName.startsWith(packageName)) { if (otherPackageName.length == packageName.length) return true if (withSubpackages) { if (otherPackageName[packageName.length] == '.') return true } } return false } val isSpecial: Boolean get() = this == ALL_OTHER_IMPORTS_ENTRY || this == ALL_OTHER_ALIAS_IMPORTS_ENTRY override fun toString(): String { return packageName } } ================================================ FILE: kotlin-eclipse-aspects/META-INF/MANIFEST.MF ================================================ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: kotlin-eclipse-aspects Bundle-SymbolicName: org.jetbrains.kotlin.aspects Bundle-Version: 0.8.24.qualifier Bundle-Activator: org.jetbrains.kotlin.aspects.Activator Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, org.aspectj.runtime, org.jetbrains.kotlin.core, org.eclipse.jdt.ui, org.eclipse.pde.launching, org.eclipse.jdt.core, org.eclipse.ltk.core.refactoring, org.jetbrains.kotlin.ui, org.eclipse.debug.core, org.eclipse.jdt.debug, org.eclipse.jdt.core.manipulation Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-ActivationPolicy: lazy Bundle-Vendor: JetBrains Import-Package: org.eclipse.core.resources, org.eclipse.debug.core, org.eclipse.debug.core.sourcelookup, org.eclipse.jdt.core, org.eclipse.jdt.debug.core, org.eclipse.jdt.internal.core, org.eclipse.jdt.internal.debug.core, org.eclipse.jdt.internal.debug.core.refactoring, org.eclipse.jdt.internal.debug.ui, org.eclipse.jdt.internal.ui.packageview, org.eclipse.jdt.internal.ui.viewsupport, org.eclipse.jdt.launching, org.eclipse.jdt.launching.sourcelookup.containers, org.eclipse.jface.text, org.eclipse.swt.graphics, org.eclipse.ui.ide Eclipse-SupplementBundle: org.eclipse.jdt.debug.ui, org.eclipse.jdt.debug, org.eclipse.jdt.launching, org.eclipse.jdt.ui, org.eclipse.jdt.internal.debug.core, org.eclipse.debug.core, org.eclipse.pde.launching, org.eclipse.jdt.core Export-Package: org.jetbrains.kotlin.aspects.debug.ui, org.jetbrains.kotlin.aspects.debug.core, org.jetbrains.kotlin.aspects.navigation, org.jetbrains.kotlin.aspects.refactoring, org.jetbrains.kotlin.aspects.ui ================================================ FILE: kotlin-eclipse-aspects/META-INF/aop.xml ================================================ ================================================ FILE: kotlin-eclipse-aspects/build.properties ================================================ source.. = src/ output.. = bin/ bin.includes = META-INF/,\ . ================================================ FILE: kotlin-eclipse-aspects/pom.xml ================================================ 4.0.0 ../pom.xml kotlin.eclipse kotlin.eclipse.plugin 0.8.24-SNAPSHOT org.jetbrains.kotlin.aspects eclipse-plugin org.eclipse.tycho tycho-compiler-plugin **/*.aj org.codehaus.mojo aspectj-maven-plugin 1.14.0 process-sources compile 16 16 src ignore true compile ================================================ FILE: kotlin-eclipse-aspects/src/org/jetbrains/kotlin/aspects/Activator.java ================================================ package org.jetbrains.kotlin.aspects; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.osgi.framework.BundleContext; /** * The activator class controls the plug-in life cycle */ public class Activator extends AbstractUIPlugin { // The plug-in ID public static final String PLUGIN_ID = "org.jetbrains.kotlin.aspects"; //$NON-NLS-1$ // The shared instance private static Activator plugin; /** * The constructor */ public Activator() { } /* * (non-Javadoc) * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext) */ public void start(BundleContext context) throws Exception { super.start(context); plugin = this; } /* * (non-Javadoc) * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext) */ public void stop(BundleContext context) throws Exception { plugin = null; super.stop(context); } /** * Returns the shared instance * * @return the shared instance */ public static Activator getDefault() { return plugin; } } ================================================ FILE: kotlin-eclipse-aspects/src/org/jetbrains/kotlin/aspects/debug/core/KotlinSourceLookupAspect.aj ================================================ package org.jetbrains.kotlin.aspects.debug.core; import org.aspectj.lang.annotation.SuppressAjWarnings; import org.eclipse.core.resources.IFile; import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.debug.core.IJavaStackFrame; import org.jetbrains.kotlin.core.debug.KotlinSourceLookupNavigator; public aspect KotlinSourceLookupAspect { pointcut getSourceElement(Object object) : args(object) && execution(Object ISourceLookupDirector.getSourceElement(Object)); @SuppressAjWarnings({"adviceDidNotMatch"}) Object around(Object object) : getSourceElement(object) { Object result = proceed(object); if (result instanceof IFile) { String fileName = ((IFile) result).getName(); if (JavaCore.isJavaLikeFileName(fileName)) { return result; } } if (object instanceof IJavaStackFrame) { IJavaStackFrame frame = (IJavaStackFrame) object; IFile kotlinSourceFile = KotlinSourceLookupNavigator.INSTANCE.findKotlinSourceFile(frame); return kotlinSourceFile != null ? kotlinSourceFile : result; } return result; } } ================================================ FILE: kotlin-eclipse-aspects/src/org/jetbrains/kotlin/aspects/debug/core/KotlinStackFrameFilterAspect.aj ================================================ package org.jetbrains.kotlin.aspects.debug.core; import java.util.stream.Stream; import org.aspectj.lang.annotation.SuppressAjWarnings; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.model.IStackFrame; import org.eclipse.debug.core.model.IVariable; import org.jetbrains.kotlin.core.utils.DebugUtils; public aspect KotlinStackFrameFilterAspect { pointcut getVariables(IStackFrame receiver) : execution(* IStackFrame.getVariables()) && target(receiver); @SuppressAjWarnings({ "adviceDidNotMatch" }) IVariable[] around(IStackFrame receiver) throws DebugException : getVariables(receiver) { IVariable[] result = proceed(receiver); if (DebugUtils.hasKotlinSource(receiver)) { result = Stream.of(result) .filter(DebugUtils::isVisible) .toArray(IVariable[]::new); } return result; } } ================================================ FILE: kotlin-eclipse-aspects/src/org/jetbrains/kotlin/aspects/debug/ui/SuppressBreakpointMarkerUpdaterAspect.aj ================================================ package org.jetbrains.kotlin.aspects.debug.ui; import org.aspectj.lang.annotation.SuppressAjWarnings; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.jdt.internal.debug.ui.BreakpointMarkerUpdater; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.Position; import org.jetbrains.kotlin.ui.builder.AspectsUtils; public aspect SuppressBreakpointMarkerUpdaterAspect { pointcut updateMarker(BreakpointMarkerUpdater markerUpdater, IMarker marker, IDocument document, Position position): args(marker, document, position) && execution(boolean BreakpointMarkerUpdater.updateMarker(IMarker, IDocument, Position)) && target(markerUpdater); @SuppressAjWarnings({"adviceDidNotMatch"}) boolean around(BreakpointMarkerUpdater markerUpdater, IMarker marker, IDocument document, Position position): updateMarker(markerUpdater, marker, document, position) { IFile resource = (IFile) marker.getResource(); if (resource != null && (AspectsUtils.existsSourceFile(resource) || AspectsUtils.isScript(resource))) { return true; } return proceed(markerUpdater, marker, document, position); } } ================================================ FILE: kotlin-eclipse-aspects/src/org/jetbrains/kotlin/aspects/navigation/KotlinFindSourceAspect.aj ================================================ package org.jetbrains.kotlin.aspects.navigation; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.internal.core.SourceMapper; import org.jetbrains.kotlin.core.resolve.KotlinSourceIndex; @SuppressWarnings("restriction") public aspect KotlinFindSourceAspect { pointcut findSource(SourceMapper mapper, IType type, String simpleSourceFileName) : target(mapper) && args(type, simpleSourceFileName) && call(char[] findSource(IType, String)); char[] around(SourceMapper mapper, IType type, String simpleSourceFileName) : findSource(mapper, type, simpleSourceFileName) { char[] result = proceed(mapper, type, simpleSourceFileName); if (result == null && KotlinSourceIndex.isKotlinSource(simpleSourceFileName)) { return KotlinSourceIndex.getSource(mapper, type, simpleSourceFileName); } return result; } } ================================================ FILE: kotlin-eclipse-aspects/src/org/jetbrains/kotlin/aspects/navigation/KotlinOpenEditorAspect.aj ================================================ package org.jetbrains.kotlin.aspects.navigation; import org.aspectj.lang.annotation.SuppressAjWarnings; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility; import org.eclipse.ui.IEditorPart; import org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaElementUtil; import org.jetbrains.kotlin.ui.navigation.KotlinOpenEditor; public aspect KotlinOpenEditorAspect { pointcut openInEditor(Object inputElement, boolean activate) : args(inputElement, activate) && execution(IEditorPart EditorUtility.openInEditor(Object, boolean)); @SuppressAjWarnings({"adviceDidNotMatch"}) IEditorPart around(Object inputElement, boolean activate) : openInEditor(inputElement, activate) { if (inputElement instanceof IJavaElement) { IJavaElement javaElement = (IJavaElement) inputElement; if (EclipseJavaElementUtil.isKotlinLightClass(javaElement)) { return KotlinOpenEditor.openKotlinEditor(javaElement, activate); } if (EclipseJavaElementUtil.isKotlinBinaryElement(javaElement)) { return KotlinOpenEditor.openKotlinClassFileEditor(javaElement, activate); } } return proceed(inputElement, activate); } } ================================================ FILE: kotlin-eclipse-aspects/src/org/jetbrains/kotlin/aspects/navigation/KotlinSearchEditorOpenerAspect.aj ================================================ package org.jetbrains.kotlin.aspects.navigation; import org.aspectj.lang.annotation.SuppressAjWarnings; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility; import org.eclipse.jdt.internal.ui.search.JavaSearchEditorOpener; import org.eclipse.ui.IEditorPart; import org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaElementUtil; import org.jetbrains.kotlin.ui.navigation.KotlinOpenEditor; public aspect KotlinSearchEditorOpenerAspect { pointcut openElement(Object element) : args(element) && execution(IEditorPart JavaSearchEditorOpener.openElement(Object)); @SuppressAjWarnings({"adviceDidNotMatch"}) IEditorPart around(Object element) : openElement(element) { if (element instanceof IJavaElement) { IJavaElement javaElement = (IJavaElement) element; if (EclipseJavaElementUtil.isKotlinLightClass(javaElement)) { IEditorPart kotlinEditor = KotlinOpenEditor.openKotlinEditor(javaElement, true); EditorUtility.revealInEditor(kotlinEditor, javaElement); return null; } } return proceed(element); } } ================================================ FILE: kotlin-eclipse-aspects/src/org/jetbrains/kotlin/aspects/refactoring/KotlinBinaryReferencesAspect.aj ================================================ package org.jetbrains.kotlin.aspects.refactoring; import org.aspectj.lang.annotation.SuppressAjWarnings; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.search.SearchMatch; import org.eclipse.jdt.internal.corext.refactoring.base.ReferencesInBinaryContext; import org.eclipse.ltk.core.refactoring.RefactoringStatus; import org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaElementUtil; @SuppressWarnings("restriction") public aspect KotlinBinaryReferencesAspect { pointcut addErrorIfNecessary(RefactoringStatus status) : args(status) && execution(void ReferencesInBinaryContext.addErrorIfNecessary(RefactoringStatus)); // JDT report about error if there are binary references for rename @SuppressAjWarnings({"adviceDidNotMatch"}) void around(RefactoringStatus status) : addErrorIfNecessary(status) { ReferencesInBinaryContext targetObject = (ReferencesInBinaryContext) thisJoinPoint.getTarget(); boolean hasKotlinReference = false; for (SearchMatch match : targetObject.getMatches()) { Object element = match.getElement(); if (element instanceof IJavaElement && EclipseJavaElementUtil.isKotlinLightClass((IJavaElement) element)) { hasKotlinReference = true; break; } } if (!hasKotlinReference) { proceed(status); } } } ================================================ FILE: kotlin-eclipse-aspects/src/org/jetbrains/kotlin/aspects/refactoring/KotlinBreakpointRenamingParticipantAspect.aj ================================================ package org.jetbrains.kotlin.aspects.refactoring; import org.aspectj.lang.annotation.SuppressAjWarnings; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.internal.debug.core.refactoring.BreakpointChange; import org.jetbrains.kotlin.ui.builder.AspectsUtils; @SuppressWarnings("restriction") public aspect KotlinBreakpointRenamingParticipantAspect { pointcut findElement(IJavaElement parent, IJavaElement element): args(parent, element) && execution(IJavaElement BreakpointChange.findElement(IJavaElement, IJavaElement)); // BreakpointRenameParticipant operates with compilation unit to rename breakpoint configuration // Thus we disable it for Kotlin files @SuppressAjWarnings({"adviceDidNotMatch"}) IJavaElement around(IJavaElement parent, IJavaElement element): findElement(parent, element) { IResource resource = parent.getResource(); if (resource instanceof IFile && AspectsUtils.isKotlinFile((IFile) resource)) { return null; } return proceed(parent, element); } } ================================================ FILE: kotlin-eclipse-aspects/src/org/jetbrains/kotlin/aspects/refactoring/KotlinJavaDescriptorAspect.aj ================================================ package org.jetbrains.kotlin.aspects.refactoring; import org.aspectj.lang.annotation.SuppressAjWarnings; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.WorkingCopyOwner; import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorUtil; import org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaElementUtil; import org.jetbrains.kotlin.ui.refactorings.rename.KotlinLightElementsFactory; public aspect KotlinJavaDescriptorAspect { pointcut handleToElement(final WorkingCopyOwner owner, final String project, final String handle, final boolean check) : args(owner, project, handle, check) && execution(IJavaElement JavaRefactoringDescriptorUtil.handleToElement(WorkingCopyOwner, String, String, boolean)); @SuppressAjWarnings({"adviceDidNotMatch"}) IJavaElement around(final WorkingCopyOwner owner, final String project, final String handle, final boolean check) : handleToElement(owner, project, handle, check) { IJavaElement javaElement = proceed(owner, project, handle, check); if (EclipseJavaElementUtil.isKotlinLightClass(javaElement)) { return KotlinLightElementsFactory.createLightElement(javaElement); } return javaElement; } } ================================================ FILE: kotlin-eclipse-aspects/src/org/jetbrains/kotlin/aspects/refactoring/KotlinRefactoringChecksAspect.aj ================================================ package org.jetbrains.kotlin.aspects.refactoring; import org.aspectj.lang.annotation.SuppressAjWarnings; import org.eclipse.jdt.core.IMember; import org.eclipse.jdt.internal.corext.refactoring.Checks; import org.eclipse.ltk.core.refactoring.RefactoringStatus; import org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaElementUtil; public aspect KotlinRefactoringChecksAspect { pointcut checkIfCuBroken(IMember member) : args(member) && execution(RefactoringStatus Checks.checkIfCuBroken(IMember)); // Disable checking of compilation unit for Kotlin files @SuppressAjWarnings({"adviceDidNotMatch"}) RefactoringStatus around(IMember member) : checkIfCuBroken(member) { if (EclipseJavaElementUtil.isKotlinLightClass(member)) { return new RefactoringStatus(); } return proceed(member); } } ================================================ FILE: kotlin-eclipse-aspects/src/org/jetbrains/kotlin/aspects/refactoring/KotlinRefactoringTypeAspect.aj ================================================ package org.jetbrains.kotlin.aspects.refactoring; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.aspectj.lang.annotation.SuppressAjWarnings; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.internal.corext.refactoring.rename.RenameTypeProcessor; import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager; import org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaElementUtil; @SuppressWarnings("restriction") public aspect KotlinRefactoringTypeAspect { pointcut addTypeDeclarationUpdate(TextChangeManager manager) : args(manager) && execution(void RenameTypeProcessor.addTypeDeclarationUpdate(TextChangeManager)); // Prohibit renaming Kotlin type declaration from JDT @SuppressAjWarnings({"adviceDidNotMatch"}) void around(TextChangeManager manager) : addTypeDeclarationUpdate(manager) { try { Method method = RenameTypeProcessor.class.getDeclaredMethod("getType"); IType type = (IType) method.invoke(thisJoinPoint.getTarget()); if (!EclipseJavaElementUtil.isKotlinLightClass(type)) { proceed(manager); } } catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { // skip } } } ================================================ FILE: kotlin-eclipse-aspects/src/org/jetbrains/kotlin/aspects/refactoring/KotlinRemoveDeclarationUpdateAspect.aj ================================================ package org.jetbrains.kotlin.aspects.refactoring; import org.aspectj.lang.annotation.SuppressAjWarnings; import org.eclipse.jdt.internal.corext.refactoring.rename.RenameNonVirtualMethodProcessor; import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager; import org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaElementUtil; @SuppressWarnings("restriction") public aspect KotlinRemoveDeclarationUpdateAspect { pointcut addDeclarationUpdate(TextChangeManager manager) : args(manager) && execution(void RenameNonVirtualMethodProcessor.addDeclarationUpdate(TextChangeManager)); // Prohibit renaming Kotlin method declaration from JDT @SuppressAjWarnings({"adviceDidNotMatch"}) void around(TextChangeManager manager) : addDeclarationUpdate(manager) { RenameNonVirtualMethodProcessor processor = (RenameNonVirtualMethodProcessor) thisJoinPoint.getTarget(); if (EclipseJavaElementUtil.isKotlinLightClass(processor.getMethod())) { return; } proceed(manager); } } ================================================ FILE: kotlin-eclipse-aspects/src/org/jetbrains/kotlin/aspects/refactoring/KotlinRenameFromJavaAspect.aj ================================================ package org.jetbrains.kotlin.aspects.refactoring; import org.aspectj.lang.annotation.SuppressAjWarnings; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.internal.ui.refactoring.actions.RenameJavaElementAction; import org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaElementUtil; import org.jetbrains.kotlin.ui.refactorings.rename.KotlinLightElementsFactory; public aspect KotlinRenameFromJavaAspect { pointcut getJavaElementFromEditor() : args() && execution(IJavaElement RenameJavaElementAction.getJavaElementFromEditor()); @SuppressAjWarnings({"adviceDidNotMatch"}) IJavaElement around() : getJavaElementFromEditor() { IJavaElement javaElement = proceed(); if (EclipseJavaElementUtil.isKotlinLightClass(javaElement)) { return KotlinLightElementsFactory.createLightElement(javaElement); } return javaElement; } } ================================================ FILE: kotlin-eclipse-aspects/src/org/jetbrains/kotlin/aspects/refactoring/KotlinRippleMethodFinderAspect.aj ================================================ package org.jetbrains.kotlin.aspects.refactoring; import org.aspectj.lang.annotation.SuppressAjWarnings; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.WorkingCopyOwner; import org.eclipse.jdt.internal.corext.refactoring.base.ReferencesInBinaryContext; import org.eclipse.jdt.internal.corext.refactoring.rename.RippleMethodFinder2; import org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaElementUtil; @SuppressWarnings("restriction") public aspect KotlinRippleMethodFinderAspect { pointcut getRelatedMethods(IMethod method, ReferencesInBinaryContext binaryRefs, IProgressMonitor pm, WorkingCopyOwner owner) : args(method, binaryRefs, pm, owner) && execution(IMethod[] RippleMethodFinder2.getRelatedMethods(IMethod, ReferencesInBinaryContext, IProgressMonitor, WorkingCopyOwner)); @SuppressAjWarnings({"adviceDidNotMatch"}) IMethod[] around(IMethod method, ReferencesInBinaryContext binaryRefs, IProgressMonitor pm, WorkingCopyOwner owner) : getRelatedMethods(method, binaryRefs, pm, owner) { if (EclipseJavaElementUtil.isKotlinLightClass(method)) { return new IMethod[] { method }; } return proceed(method, binaryRefs, pm, owner); } } ================================================ FILE: kotlin-eclipse-aspects/src/org/jetbrains/kotlin/aspects/ui/PackageExplorerLabelProviderAspect.aj ================================================ package org.jetbrains.kotlin.aspects.ui; import org.eclipse.jdt.internal.ui.packageview.PackageExplorerContentProvider; import org.eclipse.jdt.internal.ui.packageview.PackageExplorerLabelProvider; import org.jetbrains.kotlin.ui.KotlinAwarePackageExplorerLabelProvider; @SuppressWarnings("restriction") public aspect PackageExplorerLabelProviderAspect { /** * Replaces all instances of {@link PackageExplorerLabelProvider} * with instances of {@link KotlinAwarePackageExplorerLabelProvider} * * It affects classes {@link JavaNavigatorLabelProvider} and {@link PackageExplorerPart}, * which provides icons for Project Explorer and Package Explorer, respectively. */ PackageExplorerLabelProvider around(PackageExplorerContentProvider cp) : call(PackageExplorerLabelProvider.new(PackageExplorerContentProvider)) && args(cp) { return new KotlinAwarePackageExplorerLabelProvider(cp); } } ================================================ FILE: kotlin-eclipse-core/META-INF/MANIFEST.MF ================================================ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: kotlin-eclipse-core Bundle-SymbolicName: org.jetbrains.kotlin.core;singleton:=true Bundle-Version: 0.8.24.qualifier Bundle-Activator: org.jetbrains.kotlin.core.Activator Bundle-Vendor: JetBrains Require-Bundle: org.jetbrains.kotlin.bundled-compiler, org.eclipse.core.runtime, org.eclipse.jdt.core, org.eclipse.jdt.launching, org.eclipse.debug.core, org.eclipse.core.filesystem, org.eclipse.core.expressions, org.eclipse.jdt.junit Bundle-ActivationPolicy: lazy Import-Package: com.intellij.codeInsight, com.intellij.openapi.components, kotlin.script.experimental.annotations, kotlin.script.experimental.api, kotlin.script.experimental.dependencies, kotlin.script.experimental.host, kotlin.script.experimental.util, kotlin.script.experimental.jvm, org.eclipse.core.filesystem, org.eclipse.core.resources, org.eclipse.debug.internal.ui.viewers, org.eclipse.jdt.core, org.eclipse.jdt.debug.core, org.eclipse.jdt.internal.core, org.eclipse.jdt.internal.corext.dom, org.eclipse.jdt.internal.debug.core, org.eclipse.jdt.internal.debug.core.breakpoints, org.eclipse.jdt.junit.launcher, org.eclipse.jdt.ui, org.eclipse.jface.text, org.jetbrains.kotlin.resolve.sam Export-Package: org.jetbrains.kotlin.core, org.jetbrains.kotlin.core.asJava, org.jetbrains.kotlin.core.builder, org.jetbrains.kotlin.core.compiler, org.jetbrains.kotlin.core.debug, org.jetbrains.kotlin.core.filesystem, org.jetbrains.kotlin.core.formatting, org.jetbrains.kotlin.core.imports, org.jetbrains.kotlin.core.launch, org.jetbrains.kotlin.core.log, org.jetbrains.kotlin.core.model, org.jetbrains.kotlin.core.preferences, org.jetbrains.kotlin.core.references, org.jetbrains.kotlin.core.resolve, org.jetbrains.kotlin.core.resolve.lang.java.resolver, org.jetbrains.kotlin.core.resolve.lang.java.structure, org.jetbrains.kotlin.core.resolve.lang.kotlin, org.jetbrains.kotlin.core.script, org.jetbrains.kotlin.core.utils Bundle-RequiredExecutionEnvironment: JavaSE-17 ================================================ FILE: kotlin-eclipse-core/build.properties ================================================ ############################################################################### # Copyright 2000-2014 JetBrains s.r.o. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### source.. = src/ output.. = bin/ bin.includes = META-INF/,\ .,\ plugin.xml,\ schema/,\ preferences.ini ================================================ FILE: kotlin-eclipse-core/plugin.xml ================================================ ================================================ FILE: kotlin-eclipse-core/pom.xml ================================================ 4.0.0 ../pom.xml kotlin.eclipse kotlin.eclipse.plugin 0.8.24-SNAPSHOT org.jetbrains.kotlin.core eclipse-plugin src org.jetbrains.kotlin kotlin-maven-plugin ${kotlin.version} 17 compile process-sources compile org.apache.maven.plugins maven-compiler-plugin 3.10.1 17 ================================================ FILE: kotlin-eclipse-core/preferences.ini ================================================ jvmTarget=JVM_1_6 compilerPlugins/all-open/active=false compilerPlugins/all-open/jarPath=$KOTLIN_HOME/lib/allopen-compiler-plugin.jar compilerPlugins/spring/active=false compilerPlugins/spring/jarPath=$KOTLIN_HOME/lib/allopen-compiler-plugin.jar compilerPlugins/spring/args=org.jetbrains.kotlin.allopen:preset=spring compilerPlugins/no-arg/active=false compilerPlugins/no-arg/jarPath=$KOTLIN_HOME/lib/noarg-compiler-plugin.jar compilerPlugins/jpa/active=false compilerPlugins/jpa/jarPath=$KOTLIN_HOME/lib/noarg-compiler-plugin.jar compilerPlugins/jpa/args=org.jetbrains.kotlin.noarg:preset=jpa compilerPlugins/sam-with-receiver/active=false compilerPlugins/sam-with-receiver/jarPath=$KOTLIN_HOME/lib/sam-with-receiver-compiler-plugin.jar codeStyle/codeStyleId=KOTLIN_OFFICIAL ================================================ FILE: kotlin-eclipse-core/schema/org.jetbrains.kotlin.core.predefinedKotlinCodeStyle.exsd ================================================ [Enter description of this extension point.] [Enter the first release in which this extension point appears.] [Enter extension point usage example here.] [Enter API information here.] [Enter information about supplied implementation of this extension point.] ================================================ FILE: kotlin-eclipse-core/schema/org.jetbrains.kotlin.core.scriptTemplateContribution.exsd ================================================ [Enter description of this extension point.] [Enter the first release in which this extension point appears.] [Enter extension point usage example here.] [Enter API information here.] [Enter information about supplied implementation of this extension point.] ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/Activator.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core; import org.eclipse.core.resources.IResourceChangeEvent; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.Plugin; import org.eclipse.core.runtime.preferences.DefaultScope; import org.jetbrains.kotlin.core.model.KotlinAnalysisProjectCache; import org.jetbrains.kotlin.core.model.KotlinRefreshProjectListener; import org.jetbrains.kotlin.core.preferences.KotlinProperties; import org.osgi.framework.BundleContext; public class Activator extends Plugin { private static Activator plugin; public static final String PLUGIN_ID = "org.jetbrains.kotlin.core"; public Activator() { plugin = this; } public static Activator getDefault() { return plugin; } @Override public void start(BundleContext bundleContext) throws Exception { super.start(bundleContext); ResourcesPlugin.getWorkspace().addResourceChangeListener(KotlinAnalysisProjectCache.INSTANCE, IResourceChangeEvent.PRE_CLOSE | IResourceChangeEvent.PRE_DELETE | IResourceChangeEvent.PRE_BUILD); ResourcesPlugin.getWorkspace().addResourceChangeListener(KotlinRefreshProjectListener.INSTANCE, IResourceChangeEvent.PRE_REFRESH); KotlinProperties.init(); } @Override public void stop(BundleContext bundleContext) throws Exception { ResourcesPlugin.getWorkspace().removeResourceChangeListener(KotlinAnalysisProjectCache.INSTANCE); ResourcesPlugin.getWorkspace().removeResourceChangeListener(KotlinRefreshProjectListener.INSTANCE); plugin = null; } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/KotlinClasspathContainer.kt ================================================ /******************************************************************************* * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core import org.eclipse.core.runtime.IPath import org.eclipse.core.runtime.Path 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.jetbrains.kotlin.core.model.KotlinJavaManager import org.jetbrains.kotlin.core.utils.ProjectUtils import org.jetbrains.kotlin.core.utils.buildLibPath import java.util.* val runtimeContainerId: IPath = Path("org.jetbrains.kotlin.core.KOTLIN_CONTAINER") class KotlinClasspathContainer(val javaProject: IJavaProject) : IClasspathContainer { companion object { val CONTAINER_ENTRY: IClasspathEntry = JavaCore.newContainerEntry(runtimeContainerId) val LIB_RUNTIME_NAME = "kotlin-stdlib" val LIB_RUNTIME_SRC_NAME = "kotlin-stdlib-sources" val LIB_REFLECT_NAME = "kotlin-reflect" val LIB_SCRIPT_RUNTIME_NAME = "kotlin-script-runtime" val LIB_ANNOTATIONS_1_3 = "annotations-13.0" @JvmStatic fun getPathToLightClassesFolder(javaProject: IJavaProject): IPath { return Path(javaProject.project.name).append(KotlinJavaManager.KOTLIN_BIN_FOLDER).makeAbsolute() } } override fun getClasspathEntries(): Array { val entries = ArrayList() val kotlinBinFolderEntry = ProjectUtils.newExportedLibraryEntry(getPathToLightClassesFolder(javaProject)) entries.add(kotlinBinFolderEntry) val project = javaProject.project if (!ProjectUtils.isMavenProject(project) && !ProjectUtils.isGradleProject(project)) { val kotlinRuntimeEntry = JavaCore.newLibraryEntry( LIB_RUNTIME_NAME.buildLibPath(), LIB_RUNTIME_SRC_NAME.buildLibPath(), null, true) val kotlinReflectEntry = ProjectUtils.newExportedLibraryEntry(LIB_REFLECT_NAME.buildLibPath()) val kotlinScriptRuntime = ProjectUtils.newExportedLibraryEntry(LIB_SCRIPT_RUNTIME_NAME.buildLibPath()) val annotations13 = ProjectUtils.newExportedLibraryEntry(LIB_ANNOTATIONS_1_3.buildLibPath()) entries.add(kotlinRuntimeEntry) entries.add(kotlinReflectEntry) entries.add(kotlinScriptRuntime) entries.add(annotations13) } return entries.toTypedArray() } override fun getDescription(): String = "Kotlin Runtime Library" override fun getKind(): Int = IClasspathContainer.K_APPLICATION override fun getPath(): IPath = runtimeContainerId } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/KotlinClasspathContainerInitializer.kt ================================================ package org.jetbrains.kotlin.core import org.eclipse.core.resources.IFolder import org.eclipse.core.resources.IResource import org.eclipse.core.runtime.IPath import org.eclipse.core.runtime.Path import org.eclipse.jdt.core.ClasspathContainerInitializer import org.eclipse.jdt.core.IJavaProject import org.eclipse.jdt.core.JavaCore import org.jetbrains.kotlin.core.filesystem.KotlinFileSystem import org.jetbrains.kotlin.core.model.KotlinJavaManager import java.net.URI class KotlinClasspathContainerInitializer : ClasspathContainerInitializer() { override fun initialize(containerPath: IPath, javaProject: IJavaProject) { if (JavaCore.getClasspathContainer(runtimeContainerId, javaProject) !is KotlinClasspathContainer) { if (!KotlinJavaManager.hasLinkedKotlinBinFolder(javaProject.project)) { addFolderForKotlinClassFiles(javaProject) } JavaCore.setClasspathContainer(containerPath, arrayOf(javaProject), arrayOf(KotlinClasspathContainer(javaProject)), null) } } } private fun setKotlinFileSystemScheme(folder: IFolder) : URI { val locationURI = folder.locationURI val path = Path(folder.project.name).append(KotlinJavaManager.KOTLIN_BIN_FOLDER).makeAbsolute() return URI( KotlinFileSystem.SCHEME, locationURI.userInfo, locationURI.host, locationURI.port, path.toPortableString(), locationURI.query, locationURI.fragment) } private fun addFolderForKotlinClassFiles(javaProject: IJavaProject) { val folder = javaProject.project.getFolder(KotlinJavaManager.KOTLIN_BIN_FOLDER) folder.createLink(setKotlinFileSystemScheme(folder), IResource.REPLACE or IResource.ALLOW_MISSING_LOCAL, null) } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/KotlinClasspathProvider.kt ================================================ package org.jetbrains.kotlin.core import org.eclipse.debug.core.ILaunchConfiguration import org.eclipse.jdt.launching.IRuntimeClasspathEntry import org.eclipse.jdt.launching.JavaRuntime import org.eclipse.jdt.launching.StandardClasspathProvider const val KOTLIN_CLASSPATH_PROVIDER_ID = "org.jetbrains.kotlin.core.kotlinClasspathProvider" class KotlinClasspathProvider : StandardClasspathProvider() { override fun computeUnresolvedClasspath(configuration: ILaunchConfiguration): Array = super.computeUnresolvedClasspath(configuration) .filterNot { it.location != null && it.location == configuration.lightClassPath } .toTypedArray() private val ILaunchConfiguration.lightClassPath: String? get() = JavaRuntime.getJavaProject(this) ?.let { KotlinClasspathContainer.getPathToLightClassesFolder(it) } ?.toPortableString() } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/asJava/BinaryClassWriter.java ================================================ package org.jetbrains.kotlin.core.asJava; import org.jetbrains.org.objectweb.asm.ClassWriter; public class BinaryClassWriter extends ClassWriter { public BinaryClassWriter() { super(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); } @Override protected String getCommonSuperClass(String type1, String type2) { try { return super.getCommonSuperClass(type1, type2); } catch (Throwable t) { // TODO: we might need at some point do more sophisticated handling return "java/lang/Object"; } } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/asJava/KotlinLightClassGeneration.kt ================================================ /******************************************************************************* * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.asJava import org.eclipse.core.resources.IFile import org.eclipse.core.resources.IProject import org.eclipse.core.runtime.Path import org.eclipse.jdt.core.JavaCore import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.codegen.KotlinCodegenFacade import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.core.builder.KotlinPsiManager import org.jetbrains.kotlin.core.filesystem.KotlinLightClassManager import org.jetbrains.kotlin.core.model.KotlinEnvironment import org.jetbrains.kotlin.core.model.KotlinJavaManager import org.jetbrains.kotlin.core.preferences.languageVersionSettings import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtCodeFragment import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtScript object KotlinLightClassGeneration { fun updateLightClasses(project: IProject, affectedFiles: Set, resourcesTreeBlocked: Boolean = false) { if (!KotlinJavaManager.hasLinkedKotlinBinFolder(project)) return KotlinPsiManager.recreateSourcesForProject(JavaCore.create(project)) KotlinLightClassManager.getInstance(project).computeLightClassesSources() KotlinLightClassManager.getInstance(project).updateLightClasses(affectedFiles, resourcesTreeBlocked) } fun buildLightClasses( analysisResult: AnalysisResult, eclipseProject: IProject, jetFiles: List, requestedClassName: String): GenerationState { val tempProps = KotlinEnvironment.getEnvironment(eclipseProject).compilerProperties val tempConfig = CompilerConfiguration().apply { put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, tempProps.languageVersionSettings) } val state = GenerationState.Builder( KotlinEnvironment.getEnvironment(eclipseProject).project, LightClassBuilderFactory(), analysisResult.moduleDescriptor, analysisResult.bindingContext, jetFiles, tempConfig) .generateDeclaredClassFilter(object : GenerationState.GenerateClassFilter() { override fun shouldGenerateCodeFragment(script: KtCodeFragment): Boolean = false override fun shouldAnnotateClass(processingClassOrObject: KtClassOrObject): Boolean = true override fun shouldGenerateClass(processingClassOrObject: KtClassOrObject): Boolean { val internalName = KotlinLightClassManager.getInternalName(processingClassOrObject) return checkByInternalName(internalName, requestedClassName) } override fun shouldGeneratePackagePart(ktFile: KtFile): Boolean { val internalName = JvmFileClassUtil.getFileClassInternalName(ktFile) return checkByInternalName(internalName, requestedClassName) } override fun shouldGenerateScript(script: KtScript): Boolean = false override fun shouldGenerateClassMembers(processingClassOrObject: KtClassOrObject): Boolean { return super.shouldGenerateClassMembers(processingClassOrObject) || processingClassOrObject.hasModifier(KtTokens.COMPANION_KEYWORD) } }).build() KotlinCodegenFacade.compileCorrectFiles(state) return state } private fun checkByInternalName(internalName: String?, requestedClassFileName: String): Boolean { if (internalName == null) return false val classFileName = Path(internalName).lastSegment() val requestedInternalName = requestedClassFileName.dropLast(".class".length) if (requestedInternalName.startsWith(classFileName)) { if (requestedInternalName.length == classFileName.length) return true if (requestedInternalName[classFileName.length] == '$') return true } return false } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/asJava/LightClassBuilderFactory.java ================================================ package org.jetbrains.kotlin.core.asJava; import java.util.Collections; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import kotlin.Pair; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.codegen.AbstractClassBuilder; import org.jetbrains.kotlin.codegen.ClassBuilder; import org.jetbrains.kotlin.codegen.ClassBuilderFactory; import org.jetbrains.kotlin.codegen.ClassBuilderMode; import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin; import org.jetbrains.org.objectweb.asm.ClassWriter; import org.jetbrains.org.objectweb.asm.FieldVisitor; import org.jetbrains.org.objectweb.asm.MethodVisitor; import com.intellij.openapi.util.Key; import com.intellij.psi.PsiElement; public class LightClassBuilderFactory implements ClassBuilderFactory { public static final Key>> JVM_SIGNATURE = Key.create("JVM_SIGNATURE"); @Override @NotNull public ClassBuilderMode getClassBuilderMode() { return ClassBuilderMode.LIGHT_CLASSES; } @Override @NotNull public ClassBuilder newClassBuilder(@NotNull JvmDeclarationOrigin origin) { return new AbstractClassBuilder.Concrete(new BinaryClassWriter()) { @Override @NotNull public MethodVisitor newMethod(@NotNull JvmDeclarationOrigin origin, int access, @NotNull String name, @NotNull String desc, @Nullable String signature, @Nullable String[] exceptions) { saveJvmSignature(origin, name, desc); return super.newMethod(origin, access, name, desc, signature, exceptions); } @Override @NotNull public FieldVisitor newField(@NotNull JvmDeclarationOrigin origin, int access, @NotNull String name, @NotNull String desc, @Nullable String signature, @Nullable Object value) { saveJvmSignature(origin, name, desc); return super.newField(origin, access, name, desc, signature, value); } private void saveJvmSignature(@NotNull JvmDeclarationOrigin origin, @NotNull String name, @NotNull String desc) { PsiElement element = origin.getElement(); if (element != null) { Set> userData = element.getUserData(JVM_SIGNATURE); if (userData == null) { userData = Collections.newSetFromMap(new ConcurrentHashMap, Boolean>()); element.putUserData(JVM_SIGNATURE, userData); } userData.add(new Pair(desc, name)); } } }; } @Override public String asText(ClassBuilder builder) { throw new UnsupportedOperationException("BINARIES generator asked for text"); } @Override public byte[] asBytes(ClassBuilder builder) { ClassWriter visitor = (ClassWriter) builder.getVisitor(); return visitor.toByteArray(); } @Override public void close() { } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/asJava/LightClassFile.java ================================================ package org.jetbrains.kotlin.core.asJava; import java.io.ByteArrayInputStream; import java.io.File; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.core.log.KotlinLogger; public class LightClassFile { private final IFile file; public LightClassFile(@NotNull IFile file) { this.file = file; } public boolean exists() { return file.exists(); } public boolean createIfNotExists() { try { if (!file.exists()) { file.create(new ByteArrayInputStream(new byte[0]), false, null); return true; } } catch (CoreException e) { KotlinLogger.logAndThrow(e); } return false; } public void touchFile() { try { file.touch(null); } catch (CoreException e) { KotlinLogger.logAndThrow(e); } } @NotNull public File asFile() { return file.getFullPath().toFile(); } @NotNull public IFile getResource() { return file; } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/asJava/elementUtils.kt ================================================ /******************************************************************************* * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.asJava import org.jetbrains.kotlin.psi.KtElement import org.eclipse.jdt.core.IMember import org.eclipse.jdt.core.IField import org.eclipse.jdt.core.IMethod import org.jetbrains.kotlin.psi.KtClass import org.jetbrains.kotlin.psi.KtConstructor import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtClassOrObject import com.intellij.psi.util.PsiTreeUtil import org.jetbrains.kotlin.name.FqName import com.intellij.psi.PsiElement import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil fun equalsJvmSignature(KtElement: KtElement, javaMember: IMember): Boolean { val jetSignatures = KtElement.getUserData(LightClassBuilderFactory.JVM_SIGNATURE) if (jetSignatures == null) return false val memberSignature = when (javaMember) { is IField -> javaMember.getTypeSignature().replace("\\.".toRegex(), "/") // Hack is IMethod -> javaMember.getSignature() else -> null } return jetSignatures.any { if (it.first == memberSignature) { return@any when { javaMember is IMethod && javaMember.isConstructor() -> KtElement is KtClass || KtElement is KtConstructor<*> else -> it.second == javaMember.getElementName() } } false } } fun getDeclaringTypeFqName(KtElement: KtElement): FqName? { val parent = PsiTreeUtil.getParentOfType(KtElement, KtClassOrObject::class.java, KtFile::class.java) return if (parent != null) getTypeFqName(parent) else null } fun getTypeFqName(element: PsiElement): FqName? { return when (element) { is KtClassOrObject -> element.getFqName() is KtFile -> JvmFileClassUtil.getFileClassInfoNoResolve(element).fileClassFqName else -> null } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/builder/KotlinPsiManager.kt ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.builder import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.util.text.StringUtilRt import com.intellij.openapi.vfs.CharsetToolkit import com.intellij.psi.PsiFileFactory import com.intellij.psi.impl.PsiFileFactoryImpl import org.eclipse.core.resources.IFile import org.eclipse.core.resources.IProject import org.eclipse.core.resources.IResource import org.eclipse.core.resources.IResourceDelta import org.eclipse.core.resources.ResourcesPlugin import org.eclipse.core.runtime.CoreException import org.eclipse.core.runtime.Path import org.eclipse.jdt.core.IClasspathEntry import org.eclipse.jdt.core.IJavaProject import org.eclipse.jdt.core.JavaCore import org.eclipse.jface.text.IDocument import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreApplicationEnvironment import org.jetbrains.kotlin.core.log.KotlinLogger import org.jetbrains.kotlin.core.model.* import org.jetbrains.kotlin.core.utils.ProjectUtils import org.jetbrains.kotlin.core.utils.asFile import org.jetbrains.kotlin.core.utils.javaProject import org.jetbrains.kotlin.core.utils.sourceFolders import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionProvider import java.io.File import java.util.Collections import java.util.HashSet import java.util.concurrent.ConcurrentHashMap import kotlin.script.experimental.host.FileScriptSource interface PsiFilesStorage { fun getPsiFile(eclipseFile: IFile): KtFile fun getPsiFile(file: IFile, expectedSourceCode: String): KtFile fun isApplicable(file: IFile): Boolean fun removeFile(file: IFile) } private class ScriptsFilesStorage : PsiFilesStorage { private val cachedKtFiles = ConcurrentHashMap() override fun getPsiFile(eclipseFile: IFile): KtFile { assert(isApplicable(eclipseFile)) { "$eclipseFile is not applicable for Kotlin scripts storage" } return cachedKtFiles.getOrPut(eclipseFile) { KotlinPsiManager.parseFile(eclipseFile)!! } } @Synchronized override fun getPsiFile(file: IFile, expectedSourceCode: String): KtFile { val sourceCodeWithouCR = StringUtilRt.convertLineSeparators(expectedSourceCode) val currentParsedFile = getPsiFile(file) if (currentParsedFile.getText() != sourceCodeWithouCR) { val jetFile = KotlinPsiManager.parseText(sourceCodeWithouCR, file)!! cachedKtFiles.put(file, jetFile) } return getPsiFile(file) } override fun isApplicable(file: IFile): Boolean = EclipseScriptDefinitionProvider.isScript(FileScriptSource(file.asFile)) override fun removeFile(file: IFile) { cachedKtFiles.remove(file) } } private class ProjectSourceFiles : PsiFilesStorage { companion object { @JvmStatic fun isKotlinFile(file: IFile): Boolean = KotlinFileType.INSTANCE.getDefaultExtension() == file.fileExtension } private val projectFiles = hashMapOf>() private val cachedKtFiles = hashMapOf() private val mapOperationLock = Any() override fun getPsiFile(eclipseFile: IFile): KtFile { synchronized (mapOperationLock) { updateProjectPsiSourcesIfNeeded(eclipseFile.getProject()) assert(existsInProjectSources(eclipseFile), { "File(" + eclipseFile.getName() + ") does not contain in the psiFiles" }) return cachedKtFiles.getOrPut(eclipseFile) { KotlinPsiManager.parseFile(eclipseFile) ?: throw IllegalStateException("Can't parse file $eclipseFile") } } } override fun getPsiFile(file: IFile, expectedSourceCode: String): KtFile { synchronized (mapOperationLock) { updatePsiFile(file, expectedSourceCode) return getPsiFile(file) } } override fun isApplicable(file: IFile): Boolean = existsInProjectSources(file) fun existsInProjectSources(file: IFile, update: Boolean = true): Boolean { synchronized (mapOperationLock) { return file.project?.let { if (update) { updateProjectPsiSourcesIfNeeded(it) } projectFiles[it]?.contains(file) } ?: false } } fun containsProject(project: IProject): Boolean { return synchronized (mapOperationLock) { projectFiles.containsKey(project) } } fun getFilesByProject(project: IProject): Set { synchronized (mapOperationLock) { updateProjectPsiSourcesIfNeeded(project) if (projectFiles.containsKey(project)) { return Collections.unmodifiableSet(projectFiles[project]) } return emptySet() } } fun addFile(file: IFile) { synchronized (mapOperationLock) { assert(KotlinNature.hasKotlinNature(file.getProject()), { "Project (" + file.getProject().getName() + ") does not have Kotlin nature" }) assert(!existsInProjectSources(file, false), { "File(" + file.getName() + ") is already added" }) projectFiles .getOrPut(file.project) { hashSetOf() } .add(file) } } override fun removeFile(file: IFile) { synchronized (mapOperationLock) { assert(existsInProjectSources(file), { "File(" + file.getName() + ") does not contain in the psiFiles" }) cachedKtFiles.remove(file) projectFiles.get(file.project)?.remove(file) } } fun addProject(project: IProject) { synchronized (mapOperationLock) { if (ProjectUtils.isAccessibleKotlinProject(project)) { addFilesToParse(JavaCore.create(project)) } } } fun removeProject(project: IProject) { synchronized (mapOperationLock) { val files = getFilesByProject(project) projectFiles.remove(project) for (file in files) { cachedKtFiles.remove(file) } } } fun addFilesToParse(javaProject: IJavaProject) { try { projectFiles.put(javaProject.getProject(), HashSet()) for (sourceFolder in javaProject.sourceFolders) { sourceFolder.resource.accept { resource -> if (resource is IFile && isKotlinFile(resource)) { addFile(resource) } true } } } catch (e: CoreException) { KotlinLogger.logError(e) } } fun updateProjectPsiSourcesIfNeeded(project: IProject) { if (projectFiles.containsKey(project)) { return } if (ProjectUtils.isAccessibleKotlinProject(project)) { updateProjectPsiSources(project, IResourceDelta.ADDED) } } fun updateProjectPsiSources(project: IProject, flag: Int) { when (flag) { IResourceDelta.ADDED -> addProject(project) IResourceDelta.REMOVED -> removeProject(project) } } fun invalidateProjectSourceFiles() { cachedKtFiles.clear() } private fun updatePsiFile(file: IFile, sourceCode: String) { val sourceCodeWithouCR = StringUtilRt.convertLineSeparators(sourceCode) synchronized (mapOperationLock) { assert(existsInProjectSources(file), { "File(" + file.getName() + ") does not contain in the psiFiles" }) val currentParsedFile = getPsiFile(file) if (!currentParsedFile.getText().equals(sourceCodeWithouCR)) { val jetFile = KotlinPsiManager.parseText(sourceCodeWithouCR, file)!! cachedKtFiles.put(file, jetFile) } } } fun addFilesIfNotPresent(project: IJavaProject) { try { with(projectFiles.getOrPut(project.project) { hashSetOf() }) { for (sourceFolder in project.sourceFolders) { sourceFolder.resource.accept { resource -> if (resource is IFile && isKotlinFile(resource) && !contains(resource)) { add(resource) } true } } } } catch (e: CoreException) { KotlinLogger.logError(e) } } } object KotlinPsiManager { private val projectSourceFiles = ProjectSourceFiles() private val scriptsFiles = ScriptsFilesStorage() fun getParsedFile(file: IFile): KtFile { return storage(file).getPsiFile(file) } private fun isApplicable(file: IFile): Boolean { return applicableStorage(file)?.isApplicable(file) ?: false } fun updateProjectPsiSources(file: IFile, flag: Int) { when (flag) { IResourceDelta.ADDED -> projectSourceFiles.addFile(file) IResourceDelta.REMOVED -> removeFile(file) else -> throw IllegalArgumentException() } } fun invalidateCachedProjectSourceFiles() { projectSourceFiles.invalidateProjectSourceFiles() } fun removeFile(file: IFile) { storage(file).removeFile(file) } fun removeProjectFromManager(project: IProject) { projectSourceFiles.updateProjectPsiSources(project, IResourceDelta.REMOVED) } fun getFilesByProject(project: IProject): Set { return projectSourceFiles.getFilesByProject(project) } fun existsSourceFile(file: IFile): Boolean { return projectSourceFiles.existsInProjectSources(file) } fun getFilesByProject(projectName: String): Set { val project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName) updateProjectPsiSourcesIfNeeded(project) return getFilesByProject(project) } private fun storage(file: IFile): PsiFilesStorage { return applicableStorage(file) ?: throw IllegalStateException("There is not applicable storage for file: $file") } private fun applicableStorage(file: IFile): PsiFilesStorage? { return when { scriptsFiles.isApplicable(file) -> scriptsFiles projectSourceFiles.isApplicable(file) -> projectSourceFiles else -> null } } private fun updateProjectPsiSourcesIfNeeded(project: IProject) { projectSourceFiles.updateProjectPsiSourcesIfNeeded(project) } private fun getParsedFile(file: IFile, expectedSourceCode: String): KtFile { return storage(file).getPsiFile(file, expectedSourceCode) } @JvmOverloads @JvmStatic fun isKotlinSourceFile( resource: IResource, javaProject: IJavaProject = JavaCore.create(resource.project)): Boolean { if (!(resource is IFile) || !KotlinFileType.INSTANCE.getDefaultExtension().equals(resource.getFileExtension())) { return false } if (!javaProject.exists()) { return false } if (!KotlinNature.hasKotlinNature(javaProject.getProject())) { return false } val classpathEntries = javaProject.getRawClasspath() val resourceRoot = resource.getFullPath().segment(1) return classpathEntries.any { classpathEntry -> classpathEntry.entryKind == IClasspathEntry.CPE_SOURCE && resourceRoot == classpathEntry.path.segment(1) } } fun parseFile(file: IFile): KtFile? { if (!file.exists()) { return null } val ioFile = File(file.getRawLocation().toOSString()) return parseText(FileUtil.loadFile(ioFile, null, true), file) } fun parseText(text: String, file: IFile): KtFile? { StringUtil.assertValidSeparators(text) val project = getEnvironment(file).project val virtualFile = KotlinLightVirtualFile(file, text) virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET) val psiFileFactory = PsiFileFactory.getInstance(project) as PsiFileFactoryImpl return psiFileFactory.trySetupPsiForFile(virtualFile, KotlinLanguage.INSTANCE, true, false) as? KtFile } @JvmStatic fun isKotlinFile(file: IFile): Boolean = KotlinFileType.INSTANCE.getDefaultExtension() == file.fileExtension @JvmStatic fun getKotlinParsedFile(file: IFile): KtFile? { return if (isApplicable(file)) getParsedFile(file) else null } @JvmStatic fun getKotlinFileIfExist(file: IFile, sourceCode: String): KtFile? { return if (isApplicable(file)) getParsedFile(file, sourceCode) else null } @JvmStatic fun getEclipseFile(jetFile: KtFile): IFile? { val virtualFile = jetFile.getVirtualFile() return if (virtualFile != null) ResourcesPlugin.getWorkspace().getRoot().getFileForLocation(Path(virtualFile.getPath())) else null } @JvmStatic fun getJavaProject(jetElement: KtElement): IJavaProject? { return getEclipseFile(jetElement.getContainingKtFile())?.let { eclipseFile -> JavaCore.create(eclipseFile.project) } } @JvmStatic fun commitFile(file: IFile, document: IDocument) { getKotlinFileIfExist(file, document.get()) } @JvmStatic fun recreateSourcesForProject(project: IJavaProject) { if (projectSourceFiles.containsProject(project.project)) { projectSourceFiles.addFilesIfNotPresent(project) } } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/compiler/KotlinCompiler.kt ================================================ package org.jetbrains.kotlin.core.compiler import com.intellij.openapi.util.Disposer import org.eclipse.jdt.core.IJavaProject import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.ERROR import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity.EXCEPTION import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.core.filesystem.KotlinLightClassManager.Companion.KOTLIN_TOUCHED_FILES_FILE_NAME import org.jetbrains.kotlin.core.launch.CompilerOutputData import org.jetbrains.kotlin.core.launch.CompilerOutputParser import org.jetbrains.kotlin.core.launch.KotlinCLICompiler import org.jetbrains.kotlin.core.model.KOTLIN_COMPILER_PATH import org.jetbrains.kotlin.core.model.KotlinEnvironment import org.jetbrains.kotlin.core.preferences.CompilerPlugin import org.jetbrains.kotlin.core.utils.DependencyResolverException import org.jetbrains.kotlin.core.utils.ProjectUtils import org.jetbrains.kotlin.incremental.makeIncrementally import java.io.* object KotlinCompiler { private fun compileKotlinFiles( javaProject: IJavaProject, compilation: (IJavaProject, File, List) -> KotlinCompilerResult ): KotlinCompilerResult = ProjectUtils.getSrcOutDirectories(javaProject) .groupingBy { it.second }.fold(mutableListOf()) { list, key -> list.apply { add(key.first) } }.onEach { (out) -> val tempFile = File(out, KOTLIN_TOUCHED_FILES_FILE_NAME).takeIf { it.exists() } tempFile?.readLines()?.map(::File)?.flatMap { tempFileToDelete -> val tempName = tempFileToDelete.nameWithoutExtension val tempFiles = tempFileToDelete.parentFile?.listFiles(FileFilter { it.name == "$tempName.class" || (it.name.startsWith("$tempName$") && it.name.endsWith(".class")) }) tempFiles?.toList() ?: emptyList() }?.distinct()?.forEach(File::delete) tempFile?.delete() out.walkTopDown().filter { it.extension == "kt" }.forEach { it.delete() } }.map { (out, sources) -> compilation(javaProject, out, sources) }.fold(KotlinCompilerResult(true, CompilerOutputData())) { previous, current -> KotlinCompilerResult(previous.result and current.result, CompilerOutputData().apply { previous.compilerOutput.list.union(current.compilerOutput.list).forEach { add(it.messageSeverity, it.message, it.messageLocation) } }) } @JvmStatic fun compileKotlinFiles(javaProject: IJavaProject): KotlinCompilerResult = compileKotlinFiles(javaProject) { project, path, sources -> execKotlinCompiler(configureCompilerArguments(project, path.absolutePath, sources)) } @JvmStatic fun compileIncrementallyFiles( javaProject: IJavaProject ): KotlinCompilerResult = compileKotlinFiles(javaProject) { project, path, sources -> execIncrementalKotlinCompiler(project, path.absoluteFile, sources) } private fun execIncrementalKotlinCompiler( javaProject: IJavaProject, outputDir: File, sourceDirs: List ): KotlinCompilerResult { val arguments = getCompilerArguments(javaProject, outputDir) val messageCollector = CompilerMessageCollector() val disposable = Disposer.newDisposable("Incremental compilation") val config = CompilerConfiguration().apply { put(JVMConfigurationKeys.NO_JDK, true) put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE) put(CLIConfigurationKeys.INTELLIJ_PLUGIN_ROOT, KOTLIN_COMPILER_PATH) } KotlinCoreEnvironment.getOrCreateApplicationEnvironmentForProduction(disposable, config) val cacheDir = File("${outputDir.parentFile.absolutePath}/cache").also { it.mkdirs() } makeIncrementally(cacheDir, sourceDirs, arguments, messageCollector) return messageCollector.getCompilerResult() } private fun execKotlinCompiler(arguments: Array): KotlinCompilerResult = with(ByteArrayOutputStream()) { KotlinCLICompiler.doMain(K2JVMCompiler(), PrintStream(this), arguments) parseCompilerOutput(BufferedReader(StringReader(this.toString()))) } private fun getCompilerArguments(javaProject: IJavaProject, outputDir: File) = K2JVMCompilerArguments().apply { val kotlinProperties = KotlinEnvironment.getEnvironment(javaProject.project).compilerProperties kotlinHome = ProjectUtils.ktHome destination = outputDir.absolutePath moduleName = "kotlin-eclipse-plugin" val jdkUndefined = kotlinProperties.isJDKHomUndefined() kotlinProperties.jdkHome?.takeUnless { jdkUndefined }?.let { jdkHomePath -> jdkHome = jdkHomePath } ?: { noJdk = true }() noStdlib = true jvmTarget = kotlinProperties.jvmTarget.description intellijPluginRoot = KOTLIN_COMPILER_PATH languageVersion = kotlinProperties.languageVersion.versionString apiVersion = kotlinProperties.apiVersion.versionString val pluginClasspathsList = mutableListOf() val pluginOptionsList = mutableListOf() kotlinProperties.compilerPlugins.entries.forEach { plugin -> plugin.jarPath?.takeIf { plugin.active }?.let { jarPath -> pluginClasspathsList.add(jarPath.replace("\$KOTLIN_HOME", ProjectUtils.ktHome)) plugin.args.forEach { arg -> pluginOptionsList.add("plugin: $arg") } } } pluginClasspaths = pluginClasspathsList.toTypedArray() pluginOptions = pluginOptionsList.toTypedArray() val tempFiles = try { ProjectUtils.collectClasspathWithDependenciesForLaunch(javaProject, jdkUndefined) } catch (e: DependencyResolverException) { e.resolvedFiles } classpath = tempFiles.joinToString(separator = System.getProperty("path.separator")) { it.absolutePath } } private fun configureCompilerArguments( javaProject: IJavaProject, outputDir: String, sourceDirs: List ): Array = with(mutableListOf()) { val kotlinProperties = KotlinEnvironment.getEnvironment(javaProject.project).compilerProperties add("-kotlin-home") add(ProjectUtils.ktHome) val jdkUndefined = kotlinProperties.isJDKHomUndefined() kotlinProperties.jdkHome?.takeUnless { jdkUndefined }?.let { jdkHomePath -> add("-jdk-home") add(jdkHomePath) } ?: add("-no-jdk") add("-no-stdlib") // Because we add runtime into the classpath add("-jvm-target") add(kotlinProperties.jvmTarget.description) add("-language-version") add(kotlinProperties.languageVersion.versionString) add("-api-version") add(kotlinProperties.apiVersion.versionString) kotlinProperties.compilerPlugins.entries.forEach { plugin -> addAll(configurePlugin(plugin)) } kotlinProperties.compilerFlags?.takeUnless { it.isBlank() }?.split("\\s+".toRegex())?.let { addAll(it) } add("-classpath") val tempFiles = try { ProjectUtils.collectClasspathWithDependenciesForLaunch(javaProject, jdkUndefined) } catch (e: DependencyResolverException) { e.resolvedFiles } add(tempFiles.joinToString(separator = System.getProperty("path.separator")) { it.absolutePath }) add("-d") add(outputDir) addAll(sourceDirs.map { it.absolutePath }) toTypedArray() } private fun configurePlugin(plugin: CompilerPlugin): Collection = mutableListOf().apply { plugin.jarPath?.takeIf { plugin.active }?.let { jarPath -> add("-Xplugin=${jarPath.replace("\$KOTLIN_HOME", ProjectUtils.ktHome)}") plugin.args.forEach { arg -> add("-P") add("plugin: $arg") } } } private class CompilerMessageCollector : MessageCollector { var hasErrors = false val severities: MutableList = mutableListOf() val compilerOutput = CompilerOutputData() override fun report( severity: CompilerMessageSeverity, message: String, location: CompilerMessageSourceLocation? ) { hasErrors == hasErrors || severity.isError severities.add(severity) if (location != null) { val messageLocation = CompilerMessageLocation.create(location.path, location.line, location.column, location.lineContent) compilerOutput.add(severity, message, messageLocation) } else { compilerOutput.add(severity, message, null) } } override fun hasErrors(): Boolean = hasErrors override fun clear() { hasErrors = false } fun getCompilerResult(): KotlinCompilerResult = KotlinCompilerResult(severities.firstOrNull { it == ERROR || it == EXCEPTION } == null, compilerOutput) } private fun parseCompilerOutput(reader: Reader): KotlinCompilerResult { val messageCollector = CompilerMessageCollector() CompilerOutputParser.parseCompilerMessagesFromReader(messageCollector, reader) return messageCollector.getCompilerResult() } } class KotlinCompilerResult(val result: Boolean, val compilerOutput: CompilerOutputData) { fun compiledCorrectly() = result } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/compiler/KotlinCompiler2.java ================================================ package org.jetbrains.kotlin.core.compiler; ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/compiler/KotlinCompilerUtils.kt ================================================ /******************************************************************************* * Copyright 2010-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jetbrains.kotlin.core.compiler import org.jetbrains.kotlin.core.compiler.KotlinCompiler.compileKotlinFiles import org.jetbrains.kotlin.core.compiler.KotlinCompiler.compileIncrementallyFiles import org.eclipse.core.runtime.CoreException import org.eclipse.jdt.core.IJavaProject import org.eclipse.core.runtime.IStatus import org.eclipse.core.runtime.Status import org.eclipse.debug.core.IStatusHandler import org.eclipse.debug.core.DebugPlugin import org.jetbrains.kotlin.core.Activator import org.jetbrains.kotlin.core.launch.CompilerOutputData object KotlinCompilerUtils { fun compileWholeProject(javaProject: IJavaProject): KotlinCompilerResult = compileKotlinFiles(javaProject) fun compileProjectIncrementally(javaProject: IJavaProject): KotlinCompilerResult = compileIncrementallyFiles(javaProject) fun handleCompilerOutput(compilerOutput: CompilerOutputWithProject) { val status: IStatus = Status(IStatus.ERROR, Activator.PLUGIN_ID, 1, "", null) val handler = DebugPlugin.getDefault().getStatusHandler(status) handler?.handleStatus(status, compilerOutput) } data class CompilerOutputWithProject(val data: CompilerOutputData, val project: IJavaProject) } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/debug/KotlinSourceLookupNavigator.java ================================================ /* * Copyright 2010-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jetbrains.kotlin.core.debug; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.debug.core.model.ISourceLocator; import org.eclipse.debug.core.sourcelookup.ISourceContainer; import org.eclipse.debug.core.sourcelookup.ISourceLookupDirector; import org.eclipse.jdt.debug.core.IJavaStackFrame; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.core.builder.KotlinPsiManager; import org.jetbrains.kotlin.core.log.KotlinLogger; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.psi.KtFile; public class KotlinSourceLookupNavigator { public static final KotlinSourceLookupNavigator INSTANCE = new KotlinSourceLookupNavigator(); private KotlinSourceLookupNavigator() { } // From JDI model we obtain path to file as "some/pckg/File.kt" and Java seeks file in folder some/pckg what might be wrong @Nullable public IFile findKotlinSourceFile(@NotNull IJavaStackFrame frame) { ISourceLocator sourceLocator = frame.getLaunch().getSourceLocator(); if (!(sourceLocator instanceof ISourceLookupDirector)) { return null; } try { return findKotlinSourceFile(frame, (ISourceLookupDirector) sourceLocator); } catch (CoreException e) { KotlinLogger.logAndThrow(e); } return null; } private IFile findKotlinSourceFile(IJavaStackFrame frame, ISourceLookupDirector lookupDirector) throws CoreException { boolean isFindDuplicates = lookupDirector.isFindDuplicates(); try { lookupDirector.setFindDuplicates(true); return findKotlinSourceFile(lookupDirector, frame); } finally { lookupDirector.setFindDuplicates(isFindDuplicates); } } @Nullable private IFile findKotlinSourceFile(@NotNull ISourceLookupDirector lookupDirector, @NotNull IJavaStackFrame frame) throws CoreException { String sourceName = frame.getSourceName(); if (sourceName == null) return null; FqName declaringPackage = new FqName(frame.getDeclaringTypeName()).parent(); for (ISourceContainer sourceContainer : lookupDirector.getSourceContainers()) { Object[] elements = sourceContainer.findSourceElements(sourceName); for (Object element : elements) { if (!(element instanceof IFile)) { continue; } IFile kotlinFile = (IFile) element; if (fileMatches(kotlinFile, declaringPackage, sourceName)) { return kotlinFile; } } } return null; } private boolean fileMatches(@NotNull IFile kotlinFile, @NotNull FqName packageName, @NotNull String sourceName) { boolean isKotlinSourceFile = kotlinFile.getName().equals(sourceName) && KotlinPsiManager.INSTANCE.existsSourceFile(kotlinFile); if (isKotlinSourceFile) { KtFile jetFile = KotlinPsiManager.INSTANCE.getParsedFile(kotlinFile); if (jetFile.getPackageFqName().equals(packageName)) { return true; } } return false; } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/filesystem/EnvironmentRemnantNature.kt ================================================ /* * Copyright 2019 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. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jetbrains.kotlin.core.filesystem import org.eclipse.core.resources.IProject import org.eclipse.core.resources.IProjectNature class EnvironmentRemnantNature: IProjectNature { companion object { const val NATURE_ID = "org.jetbrains.kotlin.core.environmentRemnant" } private lateinit var _project: IProject override fun setProject(project: IProject) { _project = project } override fun configure() { // nothing to do } override fun deconfigure() { // nothing to do } override fun getProject() = _project } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/filesystem/KotlinFileStore.kt ================================================ /******************************************************************************* * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.filesystem import org.eclipse.core.filesystem.IFileInfo import org.eclipse.core.filesystem.IFileStore import org.eclipse.core.filesystem.IFileSystem import org.eclipse.core.filesystem.provider.FileInfo import org.eclipse.core.internal.filesystem.local.LocalFile import org.eclipse.core.resources.IContainer import org.eclipse.core.resources.IFile import org.eclipse.core.resources.IProject import org.eclipse.core.resources.IResource import org.eclipse.core.resources.ResourcesPlugin import org.eclipse.core.runtime.CoreException import org.eclipse.core.runtime.IPath import org.eclipse.core.runtime.IProgressMonitor import org.eclipse.core.runtime.Path import org.eclipse.core.runtime.Status import org.eclipse.jdt.internal.compiler.util.Util import org.jetbrains.kotlin.core.asJava.KotlinLightClassGeneration import org.jetbrains.kotlin.core.model.KotlinAnalysisProjectCache import org.jetbrains.kotlin.core.resolve.KotlinAnalyzer import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream import java.io.File import java.io.InputStream import java.io.OutputStream import java.net.URI public class KotlinFileStore(file: File) : LocalFile(file) { override public fun openInputStream(options: Int, monitor: IProgressMonitor?): InputStream { val project = getProject() if (project == null) { throw CoreException(Status.CANCEL_STATUS) } val lightClass = KotlinLightClassManager.getInstance(project).getCachedLightClass(file) if (lightClass != null) { return ByteArrayInputStream(lightClass) } val jetFiles = KotlinLightClassManager.getInstance(project).getSourceFiles(file) if (jetFiles.isNotEmpty()) { val analysisResult = KotlinAnalyzer.analyzeFiles(jetFiles).analysisResult val requestedClassName = Path(file.getAbsolutePath()).lastSegment() val state = KotlinLightClassGeneration.buildLightClasses(analysisResult, project, jetFiles, requestedClassName) val generatedClass = state.factory.asList().find { val generatedClassName = Path(it.relativePath).lastSegment() requestedClassName == generatedClassName } if (generatedClass != null) { val byteArray = generatedClass.asByteArray() KotlinLightClassManager.getInstance(project).cacheLightClass(file, byteArray) return ByteArrayInputStream(byteArray) } } throw CoreException(Status.CANCEL_STATUS) } override public fun fetchInfo(options: Int, monitor: IProgressMonitor?): IFileInfo { val info = super.fetchInfo(options, monitor) as FileInfo if (Util.isClassFileName(getName())) { val workspaceFile = findFileInWorkspace() if (workspaceFile != null) { info.setExists(workspaceFile.exists()) } } else { val workspaceContainer = findFolderInWorkspace() if (workspaceContainer != null) { info.setExists(workspaceContainer.exists()) info.setDirectory(true) } } return info } override public fun childNames(options: Int, monitor: IProgressMonitor?): Array { val folder = findFolderInWorkspace() if (folder != null && folder.exists()) { return folder.members() .map { it.getName() } .toTypedArray() } return emptyArray() } override fun getFileSystem(): IFileSystem = KotlinFileSystem.getInstance() override public fun mkdir(options: Int, monitor: IProgressMonitor?): IFileStore = this override public fun openOutputStream(options: Int, monitor: IProgressMonitor?): OutputStream = ByteArrayOutputStream() override public fun getChild(name: String): IFileStore = KotlinFileStore(File(file, name)) override public fun getChild(path: IPath): IFileStore = KotlinFileStore(File(file, path.toOSString())) override public fun getFileStore(path: IPath): IFileStore = KotlinFileStore(Path(file.getPath()).append(path).toFile()) override public fun getParent(): IFileStore? = file.getParentFile()?.let { KotlinFileStore(it) } fun getProject(): IProject? = findFileInWorkspace()?.let { it.project } private fun findFileInWorkspace(): IFile? { return findResourceInWorkspace { ResourcesPlugin.getWorkspace().root.findFilesForLocationURI(it) } } private fun findFolderInWorkspace(): IContainer? { return findResourceInWorkspace { ResourcesPlugin.getWorkspace().root.findContainersForLocationURI(it) } } private inline fun findResourceInWorkspace(search: (URI) -> Array?): T? { val absolutePath = file.toURI().path val pathRelatedToKtFileSystem = URI(KotlinFileSystem.SCHEME, null, absolutePath, null) val resources = search(pathRelatedToKtFileSystem) return if (resources != null && resources.isNotEmpty()) { assert(resources.size == 1, { "By ${pathRelatedToKtFileSystem} found more than one file" }) resources[0] } else { null } } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/filesystem/KotlinFileSystem.java ================================================ package org.jetbrains.kotlin.core.filesystem; import java.io.File; import java.net.URI; import org.eclipse.core.filesystem.IFileStore; import org.eclipse.core.filesystem.IFileTree; import org.eclipse.core.filesystem.provider.FileSystem; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; public class KotlinFileSystem extends FileSystem { public static final String SCHEME = "org.jetbrains.kotlin.core.filesystem"; private static KotlinFileSystem instance; public KotlinFileSystem() { instance = this; } @Override public IFileStore getStore(URI uri) { return new KotlinFileStore(new File(uri.getSchemeSpecificPart())); } @Override public boolean canDelete() { return true; } @Override public boolean canWrite() { return true; } public static KotlinFileSystem getInstance() { return instance; } @Override public IFileTree fetchFileTree(IFileStore root, IProgressMonitor monitor) throws CoreException { return super.fetchFileTree(root, monitor); } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/filesystem/KotlinLightClassManager.kt ================================================ package org.jetbrains.kotlin.core.filesystem import com.intellij.openapi.components.ServiceManager import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement import com.intellij.psi.util.PsiTreeUtil import org.eclipse.core.internal.jobs.JobStatus import org.eclipse.core.resources.* import org.eclipse.core.runtime.* import org.eclipse.jdt.core.JavaCore import org.eclipse.jdt.internal.core.util.LRUCache import org.jetbrains.kotlin.core.asJava.LightClassFile import org.jetbrains.kotlin.core.builder.KotlinPsiManager.getFilesByProject import org.jetbrains.kotlin.core.builder.KotlinPsiManager.getKotlinParsedFile import org.jetbrains.kotlin.core.builder.KotlinPsiManager.getParsedFile import org.jetbrains.kotlin.core.log.KotlinLogger.logAndThrow import org.jetbrains.kotlin.core.model.KotlinEnvironment.Companion.getEnvironment import org.jetbrains.kotlin.core.model.KotlinJavaManager import org.jetbrains.kotlin.core.model.KotlinJavaManager.getKotlinBinFolderFor import org.jetbrains.kotlin.core.utils.ProjectUtils.cleanFolder import org.jetbrains.kotlin.core.utils.ProjectUtils.getAllOutputFolders import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.* import java.io.File import java.io.IOException import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentMap import kotlin.text.Charsets.UTF_8 class KotlinLightClassManager(private val project: IProject) { private val cachedLightClasses = LRUCache(LIGHT_CLASSES_CACHE_SIZE) private val sourceFiles: ConcurrentMap> = ConcurrentHashMap() @Synchronized fun getCachedLightClass(file: File): ByteArray? { val lightClass: Any? = cachedLightClasses[file] return if (lightClass != null) lightClass as ByteArray? else null } @Synchronized fun cacheLightClass(file: File, lightClass: ByteArray) { cachedLightClasses.put(file, lightClass) } @Synchronized fun removeLightClass(file: File) { cachedLightClasses.flush(file) val tempFolders = getAllOutputFolders(JavaCore.create(project)) val tempSegments = file.path.split("[/\\\\]".toRegex()).toTypedArray() val tempRealPath = tempSegments.copyOfRange(3, tempSegments.size) for (tempFolder in tempFolders) { val tempRootFolder = tempFolder.location.toFile() var tempCurrentFolder = tempRootFolder for ((tempIndex, tempSegment) in tempRealPath.withIndex()) { if (tempIndex == tempRealPath.lastIndex) { val tempFile = File(tempCurrentFolder, tempSegment).takeIf { it.exists() } ?: break val tempTouchedFilesFile = File(tempRootFolder, KOTLIN_TOUCHED_FILES_FILE_NAME) try { if (!tempTouchedFilesFile.exists()) tempTouchedFilesFile.createNewFile() val tempLines = tempTouchedFilesFile.readLines(UTF_8).toMutableSet() tempLines.add(tempFile.absolutePath) tempTouchedFilesFile.writeText(tempLines.joinToString("\n"), UTF_8) } catch (e: IOException) { e.printStackTrace() } } else { tempCurrentFolder = File(tempCurrentFolder, tempSegment).takeIf { it.exists() } ?: break } } } } fun computeLightClassesSources() { val newSourceFilesMap: MutableMap> = HashMap() for (sourceFile in getFilesByProject(project)) { val lightClassesPaths = getLightClassesPaths(sourceFile) for (path in lightClassesPaths) { val lightClassFile = LightClassFile(project.getFile(path)) val newSourceFiles = newSourceFilesMap.computeIfAbsent(lightClassFile.asFile()) { HashSet() } newSourceFiles.add(sourceFile) } } sourceFiles.clear() sourceFiles.putAll(newSourceFilesMap) } fun updateLightClasses(affectedFiles: Set, resourceTreeBlocked: Boolean) { val toCreate: MutableList = ArrayList() val toRemove: MutableList = ArrayList() for ((key, value) in sourceFiles) { val lightClassIFile = ResourcesPlugin.getWorkspace().root.getFile(Path(key.path)) ?: continue val lightClassFile = LightClassFile(lightClassIFile) if (!lightClassFile.exists()) { toCreate.add(lightClassFile) } for (sourceFile in value) { if (affectedFiles.contains(sourceFile)) { toRemove.add(lightClassFile) break } } } if (resourceTreeBlocked) { if (toCreate.isNotEmpty() || toRemove.isNotEmpty()) { val job: WorkspaceJob = object : WorkspaceJob(WORKSPACE_JOB_ID) { override fun runInWorkspace(monitor: IProgressMonitor): IStatus { monitor.beginTask("Light class generation started", 0) updateLightClasses(toCreate, toRemove) monitor.done() return JobStatus(0, this, "Light classes generation finished") } } job.rule = ResourcesPlugin.getWorkspace().ruleFactory.createRule( project.getFolder(KotlinJavaManager.KOTLIN_BIN_FOLDER)) job.schedule() } } else { updateLightClasses(toCreate, toRemove) } } private fun updateLightClasses(toCreate: List, toRemove: List) { for (lightClassFile in toCreate) { createParentDirsFor(lightClassFile) lightClassFile.createIfNotExists() } for (lightClassFile in toRemove) { removeLightClass(lightClassFile.asFile()) lightClassFile.touchFile() } cleanOutdatedLightClasses(project) } fun getSourceFiles(file: File): List { if (sourceFiles.isEmpty()) { computeLightClassesSources() } return getSourceKtFiles(file) } private fun getSourceKtFiles(lightClass: File): List { val sourceIOFiles: Set? = sourceFiles[lightClass] if (sourceIOFiles != null) { val jetSourceFiles: MutableList = ArrayList() for (sourceFile in sourceIOFiles) { val jetFile = getKotlinParsedFile(sourceFile) if (jetFile != null) { jetSourceFiles.add(jetFile) } } return jetSourceFiles } return emptyList() } private fun getLightClassesPaths(sourceFile: IFile): List { val lightClasses: MutableList = ArrayList() val ktFile = getParsedFile(sourceFile) for (classOrObject in findLightClasses(ktFile)) { val internalName = getInternalName(classOrObject) if (internalName != null) { lightClasses.add(computePathByInternalName(internalName)) } } if (ktFile.hasTopLevelCallables()) { val newFacadeInternalName = JvmFileClassUtil.getFileClassInternalName(ktFile) lightClasses.add(computePathByInternalName(newFacadeInternalName)) } return lightClasses } private fun findLightClasses(ktFile: KtFile): List { val lightClasses = ArrayList() ktFile.acceptChildren(object : KtVisitorVoid() { override fun visitClassOrObject(classOrObject: KtClassOrObject) { lightClasses.add(classOrObject) super.visitClassOrObject(classOrObject) } override fun visitNamedFunction(function: KtNamedFunction) {} override fun visitSecondaryConstructor(constructor: KtSecondaryConstructor) {} override fun visitProperty(property: KtProperty) {} override fun visitElement(element: PsiElement) { element.acceptChildren(this) } }) return lightClasses } private fun computePathByInternalName(internalName: String): IPath { val relativePath = Path("$internalName.class") return KotlinJavaManager.KOTLIN_BIN_FOLDER.append(relativePath) } private fun cleanOutdatedLightClasses(project: IProject) { cleanFolder(getKotlinBinFolderFor(project)) { resource: IResource? -> if (resource is IFile) { val lightClass = LightClassFile(resource) val sources: Set? = sourceFiles[lightClass.asFile()] val dropLightClass = sources == null || sources.isEmpty() if (dropLightClass) { removeLightClass(lightClass.asFile()) } return@cleanFolder dropLightClass } else if (resource is IFolder) { try { return@cleanFolder resource.members().isEmpty() } catch (e: CoreException) { logAndThrow(e) } } false } } private fun createParentDirsFor(lightClassFile: LightClassFile) { val parent = lightClassFile.resource.parent as? IFolder if (parent != null && !parent.exists()) { createParentDirs(parent) } } private fun createParentDirs(folder: IFolder) { val parent = folder.parent if (!parent.exists()) { createParentDirs(parent as IFolder) } try { folder.create(true, true, null) } catch (e: CoreException) { logAndThrow(e) } } companion object { const val KOTLIN_TOUCHED_FILES_FILE_NAME = "META-INF/kotlinTouchedFiles" private const val LIGHT_CLASSES_CACHE_SIZE = 300 private const val WORKSPACE_JOB_ID = "updateLightClassesJob" fun getInstance(project: IProject): KotlinLightClassManager { val ideaProject: Project = getEnvironment(project).project return ServiceManager.getService(ideaProject, KotlinLightClassManager::class.java) } fun getInternalName(classOrObject: KtClassOrObject): String? { val fullFqName = classOrObject.fqName ?: return null val topmostClassOrObject = PsiTreeUtil.getTopmostParentOfType(classOrObject, KtClassOrObject::class.java) ?: return makeInternalByToplevel(fullFqName) val topLevelFqName = topmostClassOrObject.fqName ?: return null val nestedPart = fullFqName.asString().substring(topLevelFqName.asString().length).replace("\\.".toRegex(), "\\$") return makeInternalByToplevel(topLevelFqName) + nestedPart } private fun makeInternalByToplevel(fqName: FqName): String { return fqName.asString().replace("\\.".toRegex(), "/") } } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/filesystem/KotlinScriptFIleSystem.kt ================================================ package org.jetbrains.kotlin.core.filesystem import org.eclipse.core.filesystem.EFS import org.eclipse.core.filesystem.provider.FileInfo import org.eclipse.core.filesystem.provider.FileStore import org.eclipse.core.filesystem.provider.FileSystem import org.eclipse.core.runtime.CoreException import org.eclipse.core.runtime.IProgressMonitor import org.eclipse.core.runtime.IStatus import org.eclipse.core.runtime.Status import org.jetbrains.kotlin.core.Activator import org.jetbrains.kotlin.core.log.KotlinLogger import org.jetbrains.kotlin.core.script.EnvironmentProjectsManager import java.io.ByteArrayInputStream import java.io.ByteArrayOutputStream import java.io.InputStream import java.io.OutputStream import java.net.URI import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentMap class KotlinScriptFileSystem : FileSystem() { private val handles: ConcurrentMap = ConcurrentHashMap() private val entries: MutableMap = ConcurrentHashMap(mapOf("/environments" to Directory(emptySet()))) override fun canWrite() = true override fun canDelete() = true override fun getStore(uri: URI): EnvironmentFileStore = handles.getOrPut(uri) { EnvironmentFileStore(uri) } inner class EnvironmentFileStore(private val uri: URI) : FileStore() { private val path = uri.path.dropLastWhile { it == '/' } private val _parent: EnvironmentFileStore? = path.substringBeforeLast('/', "") .takeIf { it.isNotEmpty() } ?.let { getStore(URI(uri.scheme, it, null)) } private val isPlaceholderMetadata = path.endsWith("/.project") && _parent != null && !EnvironmentProjectsManager.wasCreated(_parent.name) override fun getName() = path.substringAfterLast('/') override fun toURI() = uri override fun childNames(options: Int, monitor: IProgressMonitor?) = (entries[path] as? Directory)?.children.orEmpty().toTypedArray() override fun getParent() = _parent override fun getChild(name: String?): EnvironmentFileStore = getStore(URI(uri.scheme, "$path/$name", null)) override fun openInputStream(options: Int, monitor: IProgressMonitor?): InputStream = when (val entry = entries[path]) { is File -> ByteArrayInputStream(entry.content) is Directory -> error(EFS.ERROR_WRONG_TYPE, "$uri is a directory") null -> if (isPlaceholderMetadata) { ByteArrayInputStream((""" ${parent?.name} ${EnvironmentRemnantNature.NATURE_ID} """.trimIndent()).toByteArray()) } else { error(EFS.ERROR_NOT_EXISTS, "$uri is not existing") } } override fun fetchInfo(options: Int, monitor: IProgressMonitor?) = FileInfo(name).apply { val entry = entries[path] setExists(entry != null || isPlaceholderMetadata) isDirectory = entry is Directory } override fun openOutputStream(options: Int, monitor: IProgressMonitor?): OutputStream { val entry = entries[path] if (entry is Directory) error(EFS.ERROR_WRONG_TYPE, "$uri is a directory") return object: ByteArrayOutputStream() { override fun close() { if (entry == null) { val parentDirectory = parent?.path?.let { entries[it] } if (parentDirectory is Directory) { entries[parent!!.path] = Directory(parentDirectory.children + name) } else { error(EFS.ERROR_NOT_EXISTS, "$uri parent is not existing") } } if (entry is File && options and EFS.APPEND != 0) { entries[path] = File(entry.content + this.toByteArray()) } else { entries[path] = File(this.toByteArray()) } } } } override fun delete(options: Int, monitor: IProgressMonitor?) { entries.remove(path) childStores(EFS.NONE, null).forEach { it.delete(options, monitor) } } override fun mkdir(options: Int, monitor: IProgressMonitor?): EnvironmentFileStore = apply { val entry = entries[path] if (entry is File) error(EFS.ERROR_WRONG_TYPE, "$uri is a file") if (entry == null) { if (options and EFS.SHALLOW == 0) { parent?.mkdir(options, monitor) } val parentDirectory = parent?.path?.let { entries[it] } if (parentDirectory is Directory) { entries[parent!!.path] = Directory(parentDirectory.children + name) } else { error(EFS.ERROR_NOT_EXISTS, "$uri parent is not existing") } entries[path] = Directory(emptySet()) } } } } private sealed class FSEntry private class File(val content: ByteArray) : FSEntry() private class Directory(val children: Set) : FSEntry() private fun error(code: Int, message: String): Nothing = throw CoreException(Status(IStatus.ERROR, Activator.PLUGIN_ID, code, message, null)) ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/formatting/KotlinCodeStyleManager.kt ================================================ package org.jetbrains.kotlin.core.formatting import com.intellij.psi.codeStyle.CodeStyleSettings import org.eclipse.core.resources.IProject import org.eclipse.core.resources.ProjectScope import org.jetbrains.kotlin.core.model.EPAttribute import org.jetbrains.kotlin.core.model.ExecutableExtensionPointDescriptor import org.jetbrains.kotlin.core.model.loadExecutableEP import org.jetbrains.kotlin.core.preferences.KotlinCodeStyleProperties import org.jetbrains.kotlin.core.utils.pairOfNotNulls import org.jetbrains.kotlin.idea.formatter.KotlinPredefinedCodeStyle import java.util.concurrent.ConcurrentHashMap private const val CODESTYLE_EXTENSION_POINT = "org.jetbrains.kotlin.core.predefinedKotlinCodeStyle" object KotlinCodeStyleManager { private val extensions by lazy { loadExecutableEP(CODESTYLE_EXTENSION_POINT, isCaching = true) } private val stylesCache = ConcurrentHashMap() private val predefinedStyles: Map by lazy { extensions .mapNotNull { it.createProvider() } .map { it.codeStyleId to it } .toMap() } val buildsystemAliases by lazy { extensions.mapNotNull { pairOfNotNulls(it.nameInBuildsystem, it.createProvider()?.name) } .toMap() } val styles: List get() = (predefinedStyles.keys + stylesCache.keys).sorted() // Can be used in the future to provide user defined code styles fun getOrCreate(id: String, settingsApplier: CodeStyleSettings.() -> Unit): CodeStyleSettings = stylesCache.getOrPut(id) { CodeStyleSettings().also { it.settingsApplier() } } fun get(id: String): CodeStyleSettings? = stylesCache[id] ?: createStyleFromPredef(id) // Uses the same logic as ConcurrentHashMap.getOrPut() but due to possible nullability cannot be expressed by that method. private fun createStyleFromPredef(id: String): CodeStyleSettings? = predefinedStyles[id] ?.let { CodeStyleSettings().also(it::apply) } ?.let { stylesCache.putIfAbsent(id, it) ?: it } fun invalidate(id: String) { stylesCache -= id } fun getStyleLabel(id: String?) = id?.let { predefinedStyles[it]?.name ?: it } ?: "unknown" } private val IProject.codeStyleSettings get() = KotlinCodeStyleProperties(ProjectScope(this)) .takeIf { it.globalsOverridden } ?: KotlinCodeStyleProperties.workspaceInstance val IProject.codeStyle: CodeStyleSettings get() { val tempId = codeStyleSettings.codeStyleId ?: "KOTLIN_OFFICIAL" return KotlinCodeStyleManager.get(tempId) ?: CodeStyleSettings() } private val ExecutableExtensionPointDescriptor.nameInBuildsystem: String? by EPAttribute ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/imports/FunctionImportFinder.kt ================================================ package org.jetbrains.kotlin.core.imports import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.scopes.MemberScope class FunctionImportFinder( val filter: (CallableDescriptor) -> Boolean ) : DeclarationDescriptorVisitorEmptyBodies, List>() { override fun visitModuleDeclaration( descriptor: ModuleDescriptor, data: List ): List = descriptor.getPackage(FqName.ROOT).accept(this, data) override fun visitPackageViewDescriptor( descriptor: PackageViewDescriptor, data: List ): List = visitMemberScope(descriptor.memberScope, data) override fun visitFunctionDescriptor( descriptor: FunctionDescriptor, data: List ): List = visitMember(descriptor) override fun visitPropertyDescriptor( descriptor: PropertyDescriptor, data: List ): List = visitMember(descriptor) private fun visitMemberScope( scope: MemberScope, data: List ): List { val possiblePackageLevelFunctions = data.filter { it.substringBefore('.', "").endsWith("Kt") } .map { it.substringAfter('.') } val groupedEntries = (data + possiblePackageLevelFunctions).groupByQualifier() return scope.getContributedDescriptors { it.asString() in groupedEntries.keys } .flatMap { it.accept(this, groupedEntries[it.name.asString()].orEmpty()) } } private fun visitMember(descriptor: CallableDescriptor): List = if (filter(descriptor)) listOf(descriptor) else emptyList() override fun visitDeclarationDescriptor( descriptor: DeclarationDescriptor, data: List ): List = emptyList() } private fun Iterable.groupByQualifier() = groupBy( keySelector = { it.substringBefore('.') }, valueTransform = { it.substringAfter('.', "") } ) ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/imports/importCandidates.kt ================================================ package org.jetbrains.kotlin.core.imports import org.eclipse.jdt.core.search.TypeNameMatch import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.idea.imports.importableFqName sealed class ImportCandidate { abstract val fullyQualifiedName: String? abstract val packageName: String? abstract val simpleName: String } class TypeCandidate(val match: TypeNameMatch) : ImportCandidate() { override val fullyQualifiedName: String? = match.fullyQualifiedName override val packageName: String? = match.packageName override val simpleName: String = match.simpleTypeName } class FunctionCandidate(val descriptor: CallableDescriptor) : ImportCandidate() { override val fullyQualifiedName: String? = descriptor.importableFqName?.asString() override val packageName: String? = descriptor.importableFqName ?.takeUnless { it.isRoot } ?.parent() ?.asString() override val simpleName: String = descriptor.name.asString() } data class UniqueAndAmbiguousImports( val uniqueImports: List, val ambiguousImports: List> ) ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/imports/importServices.kt ================================================ package org.jetbrains.kotlin.core.imports import com.intellij.psi.PsiElement import org.eclipse.jdt.core.Flags import org.eclipse.jdt.core.IMethod import org.eclipse.jdt.core.search.* import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.core.resolve.KotlinResolutionFacade import org.jetbrains.kotlin.core.utils.isImported import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.idea.imports.canBeReferencedViaImport import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver import org.jetbrains.kotlin.idea.util.ReceiverType import org.jetbrains.kotlin.idea.util.receiverTypesWithIndex import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.ImportPath import org.jetbrains.kotlin.resolve.PlatformDependentAnalyzerServices import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf val FIXABLE_DIAGNOSTICS = setOf(Errors.UNRESOLVED_REFERENCE, Errors.UNRESOLVED_REFERENCE_WRONG_RECEIVER) fun findImportCandidates( references: List, bindingContext: BindingContext, resolutionFacade: KotlinResolutionFacade, candidatesFilter: (ImportCandidate) -> Boolean ): UniqueAndAmbiguousImports { // Import candidates grouped by their ambiguity: // 0 - no candidates found, 1 - exactly one candidate, 2 - multiple candidates val groupedCandidates: Map>> = references.map { findImportCandidatesForReference(it, bindingContext, resolutionFacade, candidatesFilter) } .groupBy { it.size.coerceAtMost(2) } return UniqueAndAmbiguousImports( groupedCandidates[1].orEmpty().map { it.single() }, groupedCandidates[2].orEmpty() ) } fun findImportCandidatesForReference( reference: PsiElement, bindingContext: BindingContext, resolutionFacade: KotlinResolutionFacade, candidatesFilter: (ImportCandidate) -> Boolean ): List = (findApplicableTypes(reference.text) + findApplicableCallables(reference, bindingContext, resolutionFacade)) .filter(candidatesFilter) .distinctBy { it.fullyQualifiedName } private fun findApplicableTypes(typeName: String): List { val scope = SearchEngine.createWorkspaceScope() val foundTypes = arrayListOf() val collector = object : TypeNameMatchRequestor() { override fun acceptTypeNameMatch(match: TypeNameMatch) { if (Flags.isPublic(match.modifiers)) { foundTypes.add(match) } } } val searchEngine = SearchEngine() searchEngine.searchAllTypeNames( null, SearchPattern.R_EXACT_MATCH, typeName.toCharArray(), SearchPattern.R_EXACT_MATCH or SearchPattern.R_CASE_SENSITIVE, IJavaSearchConstants.TYPE, scope, collector, IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, null ) return foundTypes.map(::TypeCandidate) } private fun findApplicableCallables( element: PsiElement, bindingContext : BindingContext, resolutionFacade: KotlinResolutionFacade ): List { val module = resolutionFacade.moduleDescriptor val callTypeAndReceiver = (element as? KtSimpleNameExpression) ?.let { CallTypeAndReceiver.detect(it) } ?: return emptyList() val descriptorKindFilter = callTypeAndReceiver.callType.descriptorKindFilter val receiverTypes: Collection = callTypeAndReceiver .receiverTypesWithIndex(bindingContext, element, module, resolutionFacade, false) .orEmpty() val visitor = FunctionImportFinder { descriptor -> descriptor.canBeReferencedViaImport() && descriptorKindFilter.accepts(descriptor) && ( descriptor.extensionReceiverParameter == null || receiverTypes.any { descriptor.isReceiverTypeMatching(it.type) }) } return searchCallableByName(element) .let { module.accept(visitor, it) } .map { FunctionCandidate(it) } } private fun CallableDescriptor.isReceiverTypeMatching(type: KotlinType): Boolean = extensionReceiverParameter?.let { type.isSubtypeOf(it.type) } ?: true private fun searchCallableByName(element: PsiElement): List { val result = mutableListOf() val conventionOperatorName = tryFindConventionOperatorName(element) if (conventionOperatorName != null) { queryForCallables(conventionOperatorName) { result += "${it.declaringType.fullyQualifiedName}.$conventionOperatorName" } } else { queryForCallables(element.text) { result += "${it.declaringType.fullyQualifiedName}.${it.elementName}" } if (element is KtNameReferenceExpression) { // We have to look for properties even if reference expression is first element in call expression, // because `something()` can mean `getSomething().invoke()`. queryForCallables(JvmAbi.getterName(element.text)) { result += "${it.declaringType.fullyQualifiedName}.${element.text}" } } } return result } private fun tryFindConventionOperatorName(element: PsiElement): String? { val isBinary = element.parent is KtBinaryExpression val isUnary = element.parent is KtPrefixExpression if (!isBinary && !isUnary) return null return (element as? KtOperationReferenceExpression) ?.operationSignTokenType ?.let { OperatorConventions.getNameForOperationSymbol(it, isUnary, isBinary) } ?.asString() } private fun queryForCallables(name: String, collector: (IMethod) -> Unit) { val pattern = SearchPattern.createPattern( name, IJavaSearchConstants.METHOD, IJavaSearchConstants.DECLARATIONS, SearchPattern.R_EXACT_MATCH ) val requester = object : SearchRequestor() { override fun acceptSearchMatch(match: SearchMatch?) { (match?.element as? IMethod)?.also(collector) } } SearchEngine().search( pattern, arrayOf(SearchEngine.getDefaultSearchParticipant()), SearchEngine.createWorkspaceScope(), requester, null ) } class DefaultImportPredicate( platform: PlatformDependentAnalyzerServices, languageVersionSettings: LanguageVersionSettings ) : (ImportCandidate) -> Boolean { private val defaultImports = platform.getDefaultImports(languageVersionSettings, true) override fun invoke(candidate: ImportCandidate): Boolean = candidate.fullyQualifiedName ?.let { ImportPath.fromString(it) } ?.isImported(defaultImports) ?.not() ?: false } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/launch/CompilerOutputData.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.launch; import java.util.ArrayList; import java.util.List; import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation; import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity; public class CompilerOutputData { private final List data = new ArrayList(); public void add(CompilerMessageSeverity messageSeverity, String message, CompilerMessageLocation messageLocation) { data.add(new CompilerOutputElement(messageSeverity, message, messageLocation)); } public void clear() { data.clear(); } public List getList() { return data; } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/launch/CompilerOutputElement.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.launch; import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation; import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity; public class CompilerOutputElement { private final CompilerMessageSeverity messageSeverity; private final String message; private final CompilerMessageLocation messageLocation; public CompilerOutputElement (CompilerMessageSeverity messageSeverity, String message, CompilerMessageLocation messageLocation) { this.messageSeverity = messageSeverity; this.message = message; this.messageLocation = messageLocation; } public CompilerMessageSeverity getMessageSeverity() { return messageSeverity; } public String getMessage() { return message; } public CompilerMessageLocation getMessageLocation() { return messageLocation; } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/launch/CompilerOutputParser.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.launch; import java.io.IOException; import java.io.Reader; import java.util.HashMap; import java.util.Map; import java.util.Stack; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation; import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity; import org.jetbrains.kotlin.cli.common.messages.MessageCollector; import org.jetbrains.kotlin.core.log.KotlinLogger; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; public class CompilerOutputParser { public static void parseCompilerMessagesFromReader(MessageCollector messageCollector, final Reader reader) { final StringBuilder stringBuilder = new StringBuilder(); Reader wrappingReader = new Reader() { @Override public int read(char[] cbuf, int off, int len) throws IOException { int read = reader.read(cbuf, off, len); stringBuilder.append(cbuf, off, len); return read; } @Override public void close() throws IOException { } }; try { SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); parser.parse(new InputSource(wrappingReader), new CompilerOutputSAXHandler(messageCollector)); } catch (Throwable e) { String message = stringBuilder.toString(); messageCollector.report(CompilerMessageSeverity.ERROR, message, null); } finally { try { reader.close(); } catch (IOException e) { KotlinLogger.logError(e); } } } private static class CompilerOutputSAXHandler extends DefaultHandler { private static final Map CATEGORIES = new HashMap(); static { CATEGORIES.put("error", CompilerMessageSeverity.ERROR); CATEGORIES.put("warning", CompilerMessageSeverity.WARNING); CATEGORIES.put("logging", CompilerMessageSeverity.LOGGING); CATEGORIES.put("output", CompilerMessageSeverity.OUTPUT); CATEGORIES.put("exception", CompilerMessageSeverity.EXCEPTION); CATEGORIES.put("info", CompilerMessageSeverity.INFO); CATEGORIES.put("messages", CompilerMessageSeverity.INFO); } private final MessageCollector messageCollector; private final StringBuilder message = new StringBuilder(); private final Stack tags = new Stack(); private String path; private int line; private int column; public CompilerOutputSAXHandler(MessageCollector messageCollector) { this.messageCollector = messageCollector; } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { tags.push(qName); message.setLength(0); String rawPath = attributes.getValue("path"); path = rawPath == null ? null : rawPath; line = safeParseInt(attributes.getValue("line"), -1); column = safeParseInt(attributes.getValue("column"), -1); } @Override public void characters(char[] ch, int start, int length) throws SAXException { if (tags.size() == 1) { String message = new String(ch, start, length); if (!message.trim().isEmpty()) { messageCollector.report(CompilerMessageSeverity.ERROR, "Unhandled compiler output: " + message, null); } } else { message.append(ch, start, length); } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if (tags.size() == 1) { return; } String qNameLowerCase = qName.toLowerCase(); CompilerMessageSeverity category = CATEGORIES.get(qNameLowerCase); if (category == null) { messageCollector.report(CompilerMessageSeverity.ERROR, "Unknown compiler message tag: " + qName, null); category = CompilerMessageSeverity.INFO; } String text = message.toString(); messageCollector.report(category, text, CompilerMessageLocation.create(path, line, column, null)); tags.pop(); } private static int safeParseInt(String value, int defaultValue) { if (value == null) { return defaultValue; } try { return Integer.parseInt(value.trim()); } catch (NumberFormatException e) { return defaultValue; } } } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/launch/KotlinCLICompiler.kt ================================================ package org.jetbrains.kotlin.core.launch import java.io.PrintStream import org.jetbrains.kotlin.cli.common.CLICompiler import org.jetbrains.kotlin.cli.common.ExitCode import org.jetbrains.kotlin.cli.jvm.compiler.CompileEnvironmentException import org.jetbrains.kotlin.config.Services import kotlin.jvm.JvmStatic import org.jetbrains.kotlin.core.model.KOTLIN_COMPILER_PATH object KotlinCLICompiler { private val obligatoryCompilerFlags get() = arrayOf( "-Xintellij-plugin-root=" + KOTLIN_COMPILER_PATH ) @JvmStatic fun doMain(compiler: CLICompiler<*>, errorStream: PrintStream, args: Array): ExitCode { System.setProperty("java.awt.headless", "true") val exitCode = doMainNoExitWithHtmlOutput(compiler, errorStream, args) return exitCode } private fun doMainNoExitWithHtmlOutput( compiler: CLICompiler<*>, errorStream: PrintStream, args: Array): ExitCode = try { compiler.execAndOutputXml( errorStream, Services.EMPTY, *obligatoryCompilerFlags, *args) } catch (e: CompileEnvironmentException) { errorStream.println(e.message) ExitCode.INTERNAL_ERROR } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/log/kotlinLogger.kt ================================================ package org.jetbrains.kotlin.core.log import org.jetbrains.kotlin.core.Activator import org.eclipse.core.runtime.IStatus import org.eclipse.core.runtime.Status import kotlin.jvm.JvmStatic object KotlinLogger { @JvmStatic fun log(status: IStatus) { Activator.getDefault().log.log(status) } @JvmStatic fun log(severity: Int, message: String, exception: Throwable?) { log(Status(severity, Activator.PLUGIN_ID, message, exception)) } @JvmStatic fun logError(exception: Throwable) { log(IStatus.ERROR, "Unexpected Exception", exception) } @JvmStatic fun logError(message: String, exception: Throwable?) { log(IStatus.ERROR, message, exception) } @JvmStatic fun logInfo(message: String) { log(IStatus.INFO, message, null) } @JvmStatic fun logWarning(message: String) { log(IStatus.WARNING, message, null) } @JvmStatic fun logAndThrow(exception: Throwable): Nothing { logError(exception) throw exception } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/CachedEnvironment.kt ================================================ /******************************************************************************* * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.model import com.intellij.openapi.project.Project import com.intellij.openapi.util.Disposer import com.intellij.openapi.vfs.impl.ZipHandler import java.util.concurrent.ConcurrentHashMap class CachedEnvironment { private val environmentLock = Any() private val environmentCache = ConcurrentHashMap() private val ideaProjectToEclipseResource = ConcurrentHashMap() fun putEnvironment(resource: T, environment: E): Unit = synchronized(environmentLock) { environmentCache[resource] = environment ideaProjectToEclipseResource[environment.project] = resource } fun getOrCreateEnvironment(resource: T, createEnvironment: (T) -> E): E = synchronized(environmentLock) { environmentCache.getOrPut(resource) { createEnvironment(resource).also { ideaProjectToEclipseResource[it.project] = resource } } } fun removeEnvironment(resource: T) = synchronized(environmentLock) { removeEnvironmentInternal(resource) } fun removeEnvironmentIf(check: (KotlinCommonEnvironment) -> Boolean): List { val tempToRemove = environmentCache.filter { check(it.value) }.map { it.key } tempToRemove.forEach(::removeEnvironmentInternal) return tempToRemove } fun removeAllEnvironments() = synchronized(environmentLock) { environmentCache.keys.toList().forEach { removeEnvironmentInternal(it) } } private fun removeEnvironmentInternal(resource: T) { environmentCache.remove(resource)?.also { ideaProjectToEclipseResource.remove(it.project) Disposer.dispose(it.projectEnvironment.parentDisposable) ZipHandler.clearFileAccessorCache() } } fun replaceEnvironment(resource: T, createEnvironment: (T) -> E): E = synchronized(environmentLock) { removeEnvironment(resource) getOrCreateEnvironment(resource, createEnvironment) } fun getEclipseResource(ideaProject: Project): T? = synchronized(environmentLock) { ideaProjectToEclipseResource[ideaProject] } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/DummyCodeStyleManager.kt ================================================ package org.jetbrains.kotlin.core.model import com.intellij.lang.ASTNode import com.intellij.openapi.editor.Document import com.intellij.openapi.fileTypes.FileType import com.intellij.openapi.project.Project import com.intellij.openapi.util.Computable import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile import com.intellij.psi.codeStyle.ChangedRangesInfo import com.intellij.psi.codeStyle.CodeStyleManager import com.intellij.psi.codeStyle.Indent import com.intellij.util.ThrowableRunnable @Suppress("DEPRECATION") class DummyCodeStyleManager : CodeStyleManager() { override fun reformatTextWithContext(arg0: PsiFile, arg1: ChangedRangesInfo) { throw UnsupportedOperationException() } override fun reformatNewlyAddedElement(block: ASTNode, addedElement: ASTNode) { throw UnsupportedOperationException() } override fun getProject(): Project { throw UnsupportedOperationException() } override fun fillIndent(indent: Indent?, fileType: FileType?): String? { throw UnsupportedOperationException() } override fun getLineIndent(file: PsiFile, offset: Int): String? { throw UnsupportedOperationException() } override fun getLineIndent(document: Document, offset: Int): String? { throw UnsupportedOperationException() } override fun getIndent(text: String?, fileType: FileType?): Indent? { throw UnsupportedOperationException() } override fun zeroIndent(): Indent? { throw UnsupportedOperationException() } override fun reformat(element: PsiElement): PsiElement { throw UnsupportedOperationException() } override fun reformat(element: PsiElement, canChangeWhiteSpacesOnly: Boolean): PsiElement { throw UnsupportedOperationException() } override fun reformatTextWithContext(file: PsiFile, ranges: MutableCollection) { throw UnsupportedOperationException() } override fun isLineToBeIndented(file: PsiFile, offset: Int): Boolean { throw UnsupportedOperationException() } override fun adjustLineIndent(file: PsiFile, rangeToAdjust: TextRange?) { // TODO: implement } override fun adjustLineIndent(file: PsiFile, offset: Int): Int { throw UnsupportedOperationException() } override fun adjustLineIndent(document: Document, offset: Int): Int { throw UnsupportedOperationException() } override fun isSequentialProcessingAllowed(): Boolean { throw UnsupportedOperationException() } override fun reformatText(p0: PsiFile, p1: MutableCollection) { throw UnsupportedOperationException() } override fun reformatText(file: PsiFile, startOffset: Int, endOffset: Int) { throw UnsupportedOperationException() } override fun reformatRange(element: PsiElement, startOffset: Int, endOffset: Int): PsiElement = element override fun reformatRange(element: PsiElement, startOffset: Int, endOffset: Int, canChangeWhiteSpacesOnly: Boolean): PsiElement = element override fun performActionWithFormatterDisabled(r: Runnable?) { throw UnsupportedOperationException() } override fun performActionWithFormatterDisabled(r: ThrowableRunnable?) { throw UnsupportedOperationException() } override fun performActionWithFormatterDisabled(r: Computable?): T { throw UnsupportedOperationException() } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/EclipseKotlinModuleResolver.kt ================================================ package org.jetbrains.kotlin.core.model import com.intellij.openapi.vfs.VirtualFile import org.jetbrains.kotlin.load.java.structure.JavaAnnotation import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver class EclipseKotlinJavaModuleResolver : JavaModuleResolver { override fun checkAccessibility( fileFromOurModule: VirtualFile?, referencedFile: VirtualFile, referencedPackage: FqName? ): JavaModuleResolver.AccessError? = null override fun getAnnotationsForModuleOwnerOfClass(classId: ClassId): List? = null } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/EclipseScriptDefinitionProvider.kt ================================================ package org.jetbrains.kotlin.core.model import org.eclipse.osgi.internal.loader.EquinoxClassLoader import org.jetbrains.kotlin.core.builder.KotlinPsiManager import org.jetbrains.kotlin.core.script.ScriptTemplateContribution import org.jetbrains.kotlin.core.script.template.ProjectScriptTemplate import org.jetbrains.kotlin.core.utils.ProjectUtils import org.jetbrains.kotlin.core.utils.asResource import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionProvider import org.jetbrains.kotlin.scripting.resolve.KtFileScriptSource import java.io.File import java.net.URLClassLoader import kotlin.reflect.KClass import kotlin.reflect.full.hasAnnotation import kotlin.script.experimental.annotations.KotlinScript import kotlin.script.experimental.api.KotlinType import kotlin.script.experimental.api.SourceCode import kotlin.script.experimental.host.ScriptingHostConfiguration import kotlin.script.experimental.host.configurationDependencies import kotlin.script.experimental.host.getScriptingClass import kotlin.script.experimental.jvm.JvmDependency import kotlin.script.experimental.jvm.JvmGetScriptingClass private const val EXTENSION_POINT_ID = "org.jetbrains.kotlin.core.scriptTemplateContribution" class EclipseScriptDefinitionProvider : ScriptDefinitionProvider { override fun getDefaultDefinition() = scriptDefinitions.first { it.baseClassType == KotlinType(ProjectScriptTemplate::class) } override fun findDefinition(script: SourceCode): ScriptDefinition? = scriptDefinitions.first { it.isScript(script) } override fun findScriptDefinition(fileName: String): KotlinScriptDefinition? = scriptDefinitions.map { it.legacyDefinition }.first { it.isScript(fileName) } override fun getDefaultScriptDefinition() = getDefaultDefinition().legacyDefinition override fun getKnownFilenameExtensions(): Sequence = scriptDefinitions.map { it.fileExtension } override fun isScript(script: SourceCode) = Companion.isScript(script) companion object { private val contributions: List by lazy { loadExecutableEP(EXTENSION_POINT_ID) .mapNotNull { it.createProvider() } .sortedByDescending { it.priority } .map(::WrappedContribution) } private val scriptDefinitions: Sequence get() = contributions.asSequence().mapNotNull { it.definition } fun getContribution(script: SourceCode): ScriptTemplateContribution? = contributions.find { it.definition?.isScript(script) == true }?.contribution fun isScript(script: SourceCode) = scriptDefinitions.any { it.isScript(script) } fun getEnvironment(scriptFile: File) = scriptFile.asResource ?.let { KotlinPsiManager.getKotlinParsedFile(it) } ?.let { KtFileScriptSource(it) } ?.let { source -> contributions.find { it.definition?.isScript(source) == true } ?.contribution?.scriptEnvironment(scriptFile) ?: emptyMap() } } } private class WrappedContribution(val contribution: ScriptTemplateContribution) { private var _definition: ScriptDefinition? = null val definition: ScriptDefinition? get() { return _definition ?: run { try { if (contribution.template.hasAnnotation()) { ScriptDefinition.FromTemplate( baseHostConfiguration = ScriptingHostConfiguration { getScriptingClass(JvmGetScriptingClass()) configurationDependencies(JvmDependency(extractClasspath(contribution.template) + scriptingDependencies)) }, template = contribution.template, contextClass = contribution.template ) } else { ScriptDefinition.FromLegacyTemplate( hostConfiguration = ScriptingHostConfiguration { getScriptingClass(JvmGetScriptingClass()) configurationDependencies(JvmDependency(extractClasspath(contribution.template) + scriptingDependencies)) }, template = contribution.template ) } } catch (e: Exception) { null } }?.also { _definition = it } } } // TODO: hack for now, will definitely need rethinking private fun extractClasspath(kClass: KClass<*>): List { return when (val tempLoader = kClass.java.classLoader) { is EquinoxClassLoader -> tempLoader.classpathManager .hostClasspathEntries .map { entry -> entry.bundleFile.baseFile.resolve("bin") } is URLClassLoader -> tempLoader.urLs.mapNotNull { File(it.file).takeIf { it.exists() } } else -> null } ?: emptyList() } private val scriptingDependencies: List by lazy { listOf("kotlin-scripting-jvm") .map { File(ProjectUtils.buildLibPath(it)) } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinAnalysisFileCache.kt ================================================ /******************************************************************************* * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.model import org.jetbrains.kotlin.core.resolve.AnalysisResultWithProvider import org.jetbrains.kotlin.core.resolve.EclipseAnalyzerFacadeForJVM import org.jetbrains.kotlin.psi.KtFile data class FileAnalysisResults(val file: KtFile, val analysisResult: AnalysisResultWithProvider) object KotlinAnalysisFileCache { @Volatile private var lastAnalysedFileCache: FileAnalysisResults? = null @Synchronized fun getAnalysisResult(file: KtFile): AnalysisResultWithProvider { return getImmediatlyFromCache(file) ?: run { val environment = getEnvironment(file.project)!! val analysisResult = resolve(file, environment) lastAnalysedFileCache = FileAnalysisResults(file, analysisResult) lastAnalysedFileCache!!.analysisResult } } fun resetCache() { lastAnalysedFileCache = null } private fun resolve(file: KtFile, environment: KotlinCommonEnvironment): AnalysisResultWithProvider { return when (environment) { is KotlinScriptEnvironment -> EclipseAnalyzerFacadeForJVM.analyzeScript(environment, file) is KotlinEnvironment -> EclipseAnalyzerFacadeForJVM.analyzeSources(environment, listOf(file)) else -> throw IllegalArgumentException("Could not analyze file with environment: $environment") } } @Synchronized private fun getImmediatlyFromCache(file: KtFile): AnalysisResultWithProvider? { return if (lastAnalysedFileCache != null && lastAnalysedFileCache!!.file == file) lastAnalysedFileCache!!.analysisResult else null } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinAnalysisProjectCache.kt ================================================ /******************************************************************************* * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.model import org.eclipse.core.resources.IFile import org.eclipse.core.resources.IProject import org.eclipse.core.resources.IResourceChangeEvent import org.eclipse.core.resources.IResourceChangeListener import org.eclipse.jdt.core.IJavaProject import org.eclipse.jdt.core.JavaCore import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.core.builder.KotlinPsiManager import org.jetbrains.kotlin.core.resolve.EclipseAnalyzerFacadeForJVM import org.jetbrains.kotlin.core.utils.ProjectUtils import java.util.concurrent.ConcurrentHashMap object KotlinAnalysisProjectCache : IResourceChangeListener { private val cachedAnalysisResults = ConcurrentHashMap() fun resetCache(project: IProject) { synchronized(project) { cachedAnalysisResults.remove(project) } } fun resetAllCaches() { cachedAnalysisResults.keys.toList().forEach { resetCache(it) } } fun getAnalysisResult(javaProject: IJavaProject): AnalysisResult { val project = javaProject.project return synchronized(project) { val analysisResult = cachedAnalysisResults.get(project) ?: run { EclipseAnalyzerFacadeForJVM.analyzeSources( KotlinEnvironment.getEnvironment(project), ProjectUtils.getSourceFiles(javaProject.project)).analysisResult } cachedAnalysisResults.putIfAbsent(project, analysisResult) ?: analysisResult } } @Synchronized public fun getAnalysisResultIfCached(project: IProject): AnalysisResult? { return cachedAnalysisResults.get(project) } override fun resourceChanged(event: IResourceChangeEvent) { when (event.type) { IResourceChangeEvent.PRE_DELETE, IResourceChangeEvent.PRE_CLOSE, IResourceChangeEvent.PRE_BUILD -> event.delta?.accept { delta -> val resource = delta.resource if (resource is IFile) { val javaProject = JavaCore.create(resource.getProject()) if (KotlinPsiManager.isKotlinSourceFile(resource, javaProject)) { cachedAnalysisResults.remove(resource.getProject()) } return@accept false } true } } } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinCommonEnvironment.kt ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ @file:Suppress("DEPRECATION") package org.jetbrains.kotlin.core.model import com.intellij.codeInsight.* import com.intellij.codeInsight.runner.JavaMainMethodProvider import com.intellij.core.CoreApplicationEnvironment import com.intellij.core.CoreJavaFileManager import com.intellij.core.JavaCoreProjectEnvironment import com.intellij.formatting.Formatter import com.intellij.formatting.FormatterImpl import com.intellij.formatting.KotlinLanguageCodeStyleSettingsProvider import com.intellij.formatting.KotlinSettingsProvider import com.intellij.lang.MetaLanguage import com.intellij.lang.jvm.facade.JvmElementProvider import com.intellij.mock.MockProject import com.intellij.openapi.Disposable import com.intellij.openapi.components.ServiceManager import com.intellij.openapi.extensions.ExtensionPointName import com.intellij.openapi.extensions.Extensions import com.intellij.openapi.extensions.ExtensionsArea import com.intellij.openapi.fileTypes.PlainTextFileType import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.SystemInfo import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.JavaModuleSystem import com.intellij.psi.PsiElementFinder import com.intellij.psi.PsiManager import com.intellij.psi.augment.PsiAugmentProvider import com.intellij.psi.codeStyle.CodeStyleManager import com.intellij.psi.codeStyle.CodeStyleSettingsProvider import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider import com.intellij.psi.compiled.ClassFileDecompilers import com.intellij.psi.impl.PsiElementFinderImpl import com.intellij.psi.impl.PsiTreeChangePreprocessor import com.intellij.psi.impl.compiled.ClsCustomNavigationPolicy import com.intellij.psi.impl.file.impl.JavaFileManager import org.eclipse.core.runtime.IPath import org.eclipse.jdt.core.IJavaProject import org.jetbrains.kotlin.asJava.KotlinAsJavaSupport import org.jetbrains.kotlin.asJava.LightClassGenerationSupport import org.jetbrains.kotlin.asJava.finder.JavaElementFinder import org.jetbrains.kotlin.caches.resolve.KotlinCacheService import org.jetbrains.kotlin.cli.common.CliModuleVisibilityManagerImpl import org.jetbrains.kotlin.cli.jvm.compiler.* import org.jetbrains.kotlin.cli.jvm.index.JavaRoot import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesDynamicCompoundIndex import org.jetbrains.kotlin.cli.jvm.index.SingleJavaFileRootsIndex import org.jetbrains.kotlin.codegen.extensions.ClassBuilderInterceptorExtension import org.jetbrains.kotlin.codegen.extensions.ExpressionCodegenExtension import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.core.log.KotlinLogger import org.jetbrains.kotlin.core.resolve.BuiltInsReferenceResolver import org.jetbrains.kotlin.core.resolve.KotlinCacheServiceImpl import org.jetbrains.kotlin.core.resolve.KotlinSourceIndex import org.jetbrains.kotlin.core.utils.KotlinImportInserterHelper import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages import org.jetbrains.kotlin.extensions.DeclarationAttributeAltererExtension import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor import org.jetbrains.kotlin.idea.KotlinFileType import org.jetbrains.kotlin.idea.j2k.J2KPostProcessingRegistrar import org.jetbrains.kotlin.idea.j2k.J2KPostProcessingRegistrarImpl import org.jetbrains.kotlin.idea.j2k.J2kPostProcessing import org.jetbrains.kotlin.idea.util.ImportInsertHelper import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache import org.jetbrains.kotlin.load.kotlin.ModuleVisibilityManager import org.jetbrains.kotlin.parsing.KotlinParserDefinition import org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer import org.jetbrains.kotlin.resolve.ModuleAnnotationsResolver import org.jetbrains.kotlin.resolve.diagnostics.DiagnosticSuppressor import org.jetbrains.kotlin.resolve.extensions.SyntheticResolveExtension import org.jetbrains.kotlin.resolve.jvm.KotlinJavaPsiFacade import org.jetbrains.kotlin.resolve.jvm.diagnostics.DefaultErrorMessagesJvm import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionProvider import org.jetbrains.kotlin.scripting.extensions.ScriptingResolveExtension import java.io.File import kotlin.reflect.KClass import com.intellij.psi.codeStyle.CodeStyleSettingsService import com.intellij.psi.codeStyle.CodeStyleSettingsServiceImpl private fun setIdeaIoUseFallback() { if (SystemInfo.isWindows) { val properties = System.getProperties() properties.setProperty("idea.io.use.nio2", java.lang.Boolean.TRUE.toString()) if (!(SystemInfo.isJavaVersionAtLeast(1, 7, 0) && "1.7.0-ea" != SystemInfo.JAVA_VERSION)) { properties.setProperty("idea.io.use.fallback", java.lang.Boolean.TRUE.toString()) } } } abstract class KotlinCommonEnvironment(disposable: Disposable) { val project: MockProject var hasError = false val projectEnvironment: JavaCoreProjectEnvironment private val roots = LinkedHashSet() val configuration = CompilerConfiguration() abstract val javaProject: IJavaProject init { setIdeaIoUseFallback() projectEnvironment = object : JavaCoreProjectEnvironment(disposable, kotlinCoreApplicationEnvironment) { override fun preregisterServices() { registerProjectExtensionPoints(project.extensionArea) CoreApplicationEnvironment.registerExtensionPoint( project.extensionArea, JvmElementProvider.EP_NAME, JvmElementProvider::class.java ) } override fun createCoreFileManager() = KotlinCliJavaFileManagerImpl(PsiManager.getInstance(project)) } project = projectEnvironment.getProject() DeclarationAttributeAltererExtension.registerExtensionPoint(project) StorageComponentContainerContributor.registerExtensionPoint(project) with(project) { val scriptDefinitionProvider = EclipseScriptDefinitionProvider() registerService(ScriptDefinitionProvider::class.java, scriptDefinitionProvider) registerService(ModuleVisibilityManager::class.java, CliModuleVisibilityManagerImpl(true)) // For j2k converter registerService(NullableNotNullManager::class.java, KotlinNullableNotNullManager(project)) registerService( CoreJavaFileManager::class.java, ServiceManager.getService(project, JavaFileManager::class.java) as CoreJavaFileManager ) registerService(ModuleAnnotationsResolver::class.java, CliModuleAnnotationsResolver()) registerService(CodeStyleManager::class.java, DummyCodeStyleManager()) registerService(BuiltInsReferenceResolver::class.java, BuiltInsReferenceResolver(project)) registerService(KotlinSourceIndex::class.java, KotlinSourceIndex()) registerService(KotlinCacheService::class.java, KotlinCacheServiceImpl(project)) registerService(ImportInsertHelper::class.java, KotlinImportInserterHelper()) registerService(ExternalAnnotationsManager::class.java, MockExternalAnnotationsManager()) registerService(InferredAnnotationsManager::class.java, MockInferredAnnotationsManager()) val traceHolder = CliTraceHolder().also { registerService(CodeAnalyzerInitializer::class.java, it) } CliLightClassGenerationSupport(traceHolder, project).also { registerService(LightClassGenerationSupport::class.java, it) registerService(CliLightClassGenerationSupport::class.java, it) } registerService(JavaModuleResolver::class.java, EclipseKotlinJavaModuleResolver()) val area = extensionArea val javaFileManager = ServiceManager.getService(this, JavaFileManager::class.java) (javaFileManager as KotlinCliJavaFileManagerImpl) .initialize( JvmDependenciesDynamicCompoundIndex(), arrayListOf(), SingleJavaFileRootsIndex(arrayListOf()), false ) area.getExtensionPoint(PsiElementFinder.EP_NAME) .registerExtension(PsiElementFinderImpl(this, javaFileManager)) val kotlinAsJavaSupport = CliKotlinAsJavaSupport(this, traceHolder) registerService(KotlinAsJavaSupport::class.java, kotlinAsJavaSupport) area.getExtensionPoint(PsiElementFinder.EP_NAME) .registerExtension(JavaElementFinder(this)) area.getExtensionPoint(SyntheticResolveExtension.extensionPointName) .registerExtension(ScriptingResolveExtension()) registerService(KotlinJavaPsiFacade::class.java, KotlinJavaPsiFacade(this)) } configuration.put(CommonConfigurationKeys.MODULE_NAME, project.name) ExpressionCodegenExtension.Companion.registerExtensionPoint(project) registerApplicationExtensionPointsAndExtensionsFrom() ClassBuilderInterceptorExtension.registerExtensionPoint(project) } fun getRoots(): Set = roots fun getVirtualFile(location: IPath): VirtualFile? { return kotlinCoreApplicationEnvironment.localFileSystem.findFileByIoFile(location.toFile()) } fun getVirtualFileInJar(pathToJar: IPath, relativePath: String): VirtualFile? { return kotlinCoreApplicationEnvironment.jarFileSystem.findFileByPath("$pathToJar!/$relativePath") } fun isJarFile(pathToJar: IPath): Boolean { val jarFile = kotlinCoreApplicationEnvironment.jarFileSystem.findFileByPath("$pathToJar!/") return jarFile != null && jarFile.isValid } protected fun addToClasspath(path: File, rootType: JavaRoot.RootType? = null) { if (path.isFile) { val jarFile = kotlinCoreApplicationEnvironment.jarFileSystem.findFileByPath("$path!/") if (jarFile == null) { KotlinLogger.logWarning("Can't find jar: $path") return } projectEnvironment.addJarToClassPath(path) val type = rootType ?: JavaRoot.RootType.BINARY roots.add(JavaRoot(jarFile, type)) } else { val root = kotlinCoreApplicationEnvironment.localFileSystem.findFileByPath(path.absolutePath) if (root == null) { KotlinLogger.logWarning("Can't find jar: $path") return } projectEnvironment.addSourcesToClasspath(root) val type = rootType ?: JavaRoot.RootType.SOURCE roots.add(JavaRoot(root, type)) } } companion object { val kotlinCoreApplicationEnvironment: KotlinCoreApplicationEnvironment by lazy { createKotlinCoreApplicationEnvironment(Disposer.newDisposable("Root Disposable")) } } } private fun createKotlinCoreApplicationEnvironment(disposable: Disposable): KotlinCoreApplicationEnvironment = KotlinCoreApplicationEnvironment.create(disposable, false).apply { registerAppExtensionPoints() registerFileType(PlainTextFileType.INSTANCE, "xml") registerFileType(KotlinFileType.INSTANCE, "kt") registerFileType(KotlinFileType.INSTANCE, KotlinParserDefinition.STD_SCRIPT_SUFFIX) registerParserDefinition(KotlinParserDefinition()) application.registerService(Formatter::class.java, FormatterImpl()) application.registerService(KotlinBinaryClassCache::class.java, KotlinBinaryClassCache()) application.registerService(ScriptDefinitionProvider::class.java, EclipseScriptDefinitionProvider()) application.registerService(J2KPostProcessingRegistrar::class.java, object : J2KPostProcessingRegistrar { override val processings: Collection get() = emptyList() override fun priority(processing: J2kPostProcessing): Int = 0 }) application.registerService(CodeStyleSettingsService::class.java, CodeStyleSettingsServiceImpl()) } private fun registerProjectExtensionPoints(area: ExtensionsArea) { registerExtensionPoint(area, PsiTreeChangePreprocessor.EP_NAME, PsiTreeChangePreprocessor::class) registerExtensionPoint(area, PsiElementFinder.EP_NAME, PsiElementFinder::class) registerExtensionPoint(area, SyntheticResolveExtension.extensionPointName, SyntheticResolveExtension::class) } @Suppress("LocalVariableName") private fun registerApplicationExtensionPointsAndExtensionsFrom() { val EP_ERROR_MSGS = ExtensionPointName.create("org.jetbrains.defaultErrorMessages.extension") registerExtensionPointInRoot(DiagnosticSuppressor.EP_NAME, DiagnosticSuppressor::class) registerExtensionPointInRoot(EP_ERROR_MSGS, DefaultErrorMessages.Extension::class) registerExtensionPointInRoot(CodeStyleSettingsProvider.EXTENSION_POINT_NAME, KotlinSettingsProvider::class) registerExtensionPointInRoot( LanguageCodeStyleSettingsProvider.EP_NAME, KotlinLanguageCodeStyleSettingsProvider::class ) registerExtensionPointInRoot(JavaModuleSystem.EP_NAME, JavaModuleSystem::class) with(Extensions.getRootArea()) { getExtensionPoint(EP_ERROR_MSGS).registerExtension(DefaultErrorMessagesJvm()) getExtensionPoint(CodeStyleSettingsProvider.EXTENSION_POINT_NAME).registerExtension(KotlinSettingsProvider()) getExtensionPoint(LanguageCodeStyleSettingsProvider.EP_NAME).registerExtension( KotlinLanguageCodeStyleSettingsProvider() ) } } private fun registerAppExtensionPoints() { registerExtensionPointInRoot(ContainerProvider.EP_NAME, ContainerProvider::class) registerExtensionPointInRoot(ClsCustomNavigationPolicy.EP_NAME, ClsCustomNavigationPolicy::class) //TODO //registerExtensionPointInRoot(ClassFileDecompilers.EP_NAME, ClassFileDecompilers.Decompiler::class) // For j2k converter registerExtensionPointInRoot(PsiAugmentProvider.EP_NAME, PsiAugmentProvider::class) registerExtensionPointInRoot(JavaMainMethodProvider.EP_NAME, JavaMainMethodProvider::class) CoreApplicationEnvironment.registerExtensionPoint( Extensions.getRootArea(), MetaLanguage.EP_NAME, MetaLanguage::class.java ) } private fun registerExtensionPoint( area: ExtensionsArea, extensionPointName: ExtensionPointName, aClass: KClass ) { CoreApplicationEnvironment.registerExtensionPoint(area, extensionPointName, aClass.java) } private fun registerExtensionPointInRoot(extensionPointName: ExtensionPointName, aClass: KClass) { registerExtensionPoint(Extensions.getRootArea(), extensionPointName, aClass) } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinEnvironment.kt ================================================ /******************************************************************************* * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.model import com.intellij.core.CoreJavaFileManager import com.intellij.openapi.Disposable import com.intellij.openapi.application.ApplicationManager import com.intellij.openapi.components.ServiceManager import com.intellij.openapi.project.Project import com.intellij.openapi.util.Disposer import com.intellij.psi.PsiElementFinder import com.intellij.psi.impl.PsiElementFinderImpl import com.intellij.psi.impl.file.impl.JavaFileManager import org.eclipse.core.resources.IFile import org.eclipse.core.resources.IProject import org.eclipse.core.resources.IResource import org.eclipse.core.resources.ProjectScope 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.internal.core.JavaProject import org.eclipse.osgi.internal.loader.EquinoxClassLoader import org.jetbrains.kotlin.asJava.classes.FacadeCache import org.jetbrains.kotlin.cli.jvm.compiler.CliVirtualFileFinderFactory import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCliJavaFileManagerImpl import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndexImpl import org.jetbrains.kotlin.cli.jvm.index.SingleJavaFileRootsIndex import org.jetbrains.kotlin.compiler.plugin.CliOptionValue import org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar import org.jetbrains.kotlin.compiler.plugin.parsePluginOption import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.JVMConfigurationKeys import org.jetbrains.kotlin.container.ComponentProvider import org.jetbrains.kotlin.container.StorageComponentContainer import org.jetbrains.kotlin.container.useInstance import org.jetbrains.kotlin.core.KotlinClasspathContainer import org.jetbrains.kotlin.core.builder.KotlinPsiManager import org.jetbrains.kotlin.core.filesystem.KotlinLightClassManager import org.jetbrains.kotlin.core.log.KotlinLogger import org.jetbrains.kotlin.core.preferences.CompilerPlugin import org.jetbrains.kotlin.core.preferences.KotlinBuildingProperties import org.jetbrains.kotlin.core.preferences.KotlinProperties import org.jetbrains.kotlin.core.resolve.lang.kotlin.EclipseVirtualFileFinderFactory import org.jetbrains.kotlin.core.utils.DependencyResolverException import org.jetbrains.kotlin.core.utils.ProjectUtils import org.jetbrains.kotlin.core.utils.asFile import org.jetbrains.kotlin.core.utils.buildLibPath import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.extensions.AnnotationBasedExtension import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor import org.jetbrains.kotlin.load.kotlin.MetadataFinderFactory import org.jetbrains.kotlin.load.kotlin.VirtualFileFinderFactory import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.platform.jvm.JvmPlatform import org.jetbrains.kotlin.psi.KtModifierListOwner import org.jetbrains.kotlin.resolve.sam.SamWithReceiverResolver import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionProvider import org.jetbrains.kotlin.scripting.definitions.annotationsForSamWithReceivers import java.io.File import java.net.URL import java.net.URLClassLoader import java.util.* import kotlin.script.experimental.api.ScriptCompilationConfiguration import kotlin.script.experimental.dependencies.ScriptDependencies import kotlin.script.experimental.host.FileScriptSource val KOTLIN_COMPILER_PATH = ProjectUtils.buildLibPath("kotlin-compiler") fun getEnvironment(eclipseFile: IFile): KotlinCommonEnvironment { return if (KotlinScriptEnvironment.isScript(eclipseFile)) { KotlinScriptEnvironment.getEnvironment(eclipseFile) } else { KotlinEnvironment.getEnvironment(eclipseFile.project) } } fun getEnvironment(ideaProject: Project): KotlinCommonEnvironment? { val eclipseResource = getEclipseResource(ideaProject) ?: return null return when (eclipseResource) { is IFile -> KotlinScriptEnvironment.getEnvironment(eclipseResource) is IProject -> KotlinEnvironment.getEnvironment(eclipseResource) else -> throw IllegalStateException("Could not get environment for resource: $eclipseResource") } } fun getEclipseResource(ideaProject: Project): IResource? { val project = KotlinEnvironment.getJavaProject(ideaProject) if (project != null) { return project } return KotlinScriptEnvironment.getEclipseFile(ideaProject) } class KotlinScriptEnvironment private constructor( private val eclipseFile: IFile, val dependencies: ScriptDependencies?, disposable: Disposable ) : KotlinCommonEnvironment(disposable) { val definition: ScriptDefinition? = ScriptDefinitionProvider.getInstance(project) ?.findDefinition(FileScriptSource(eclipseFile.asFile)) val definitionClasspath: Collection = definition?.contextClassLoader?.let(::classpathFromClassloader).orEmpty() override val javaProject: IJavaProject = JavaCore.create(eclipseFile.project) init { configureClasspath() configuration.put(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS, listOfNotNull(definition)) definition?.compilationConfiguration?.get(ScriptCompilationConfiguration.annotationsForSamWithReceivers) ?.map { it.typeName } ?.let { CliSamWithReceiverComponentContributor(it) } ?.also { StorageComponentContainerContributor.registerExtension(project, it) } val index = JvmDependenciesIndexImpl(getRoots().toList()) val area = project.extensionArea with(area.getExtensionPoint(PsiElementFinder.EP_NAME)) { registerExtension(PsiElementFinderImpl(project, ServiceManager.getService(project, JavaFileManager::class.java))) } index.indexedRoots.forEach { projectEnvironment.addSourcesToClasspath(it.file) } val singleJavaFileRoots = getRoots().filter { !it.file.isDirectory && it.file.extension == "java" } val fileManager = ServiceManager.getService(project, CoreJavaFileManager::class.java) (fileManager as KotlinCliJavaFileManagerImpl).initialize( index, emptyList(), SingleJavaFileRootsIndex(singleJavaFileRoots), configuration.getBoolean(JVMConfigurationKeys.USE_PSI_CLASS_FILES_READING)) val finderFactory = CliVirtualFileFinderFactory(index) project.registerService(MetadataFinderFactory::class.java, finderFactory) project.registerService(VirtualFileFinderFactory::class.java, finderFactory) project.registerService(FacadeCache::class.java, FacadeCache(project)) project.registerService(KotlinLightClassManager::class.java, KotlinLightClassManager(javaProject.project)) // definition?.dependencyResolver?.also { project.registerService(DependenciesResolver::class.java, it) } } companion object { private val KOTLIN_RUNTIME_PATH = KotlinClasspathContainer.LIB_RUNTIME_NAME.buildLibPath() private val KOTLIN_SCRIPT_RUNTIME_PATH = KotlinClasspathContainer.LIB_SCRIPT_RUNTIME_NAME.buildLibPath() private val cachedEnvironment = CachedEnvironment() @JvmStatic fun getEnvironment(file: IFile): KotlinScriptEnvironment { checkIsScript(file) return cachedEnvironment.getOrCreateEnvironment(file) { KotlinScriptEnvironment(it, null, Disposer.newDisposable("Scripting Env ${file.asFile.absolutePath}")) } } @JvmStatic fun removeKotlinEnvironment(file: IFile) { checkIsScript(file) cachedEnvironment.removeEnvironment(file) } fun removeAllEnvironments() { cachedEnvironment.removeAllEnvironments() } fun removeEnvironmentIf(check: (KotlinCommonEnvironment) -> Boolean) { cachedEnvironment.removeEnvironmentIf(check) } @JvmStatic fun getEclipseFile(project: Project): IFile? = cachedEnvironment.getEclipseResource(project) fun isScript(file: IFile): Boolean = EclipseScriptDefinitionProvider.isScript(FileScriptSource(file.asFile)) private fun checkIsScript(file: IFile) { if (!isScript(file)) { throw IllegalArgumentException("KotlinScriptEnvironment can work only with scripts, not ${file.name}") } } fun updateDependencies(file: IFile, newDependencies: ScriptDependencies?) { cachedEnvironment.replaceEnvironment(file) { KotlinScriptEnvironment(file, newDependencies, Disposer.newDisposable("Scripting Env ${file.asFile.absolutePath}")) .apply { addDependenciesToClasspath(newDependencies) } } KotlinPsiManager.removeFile(file) } } private fun configureClasspath() { addToClasspath(KOTLIN_RUNTIME_PATH.toFile()) addToClasspath(KOTLIN_SCRIPT_RUNTIME_PATH.toFile()) definitionClasspath.forEach { addToClasspath(it) } if (!javaProject.exists()) return val tempFiles = try { ProjectUtils.collectClasspathWithDependenciesForBuild(javaProject) } catch (e: DependencyResolverException) { hasError = true e.resolvedFiles } tempFiles.forEach(::addToClasspath) } private fun addDependenciesToClasspath(dependencies: ScriptDependencies?) { dependencies?.classpath?.forEach { addToClasspath(it) } } private fun addJREToClasspath() { val project = eclipseFile.project if (JavaProject.hasJavaNature(project)) { val javaProject = JavaCore.create(project) javaProject.rawClasspath.mapNotNull { entry -> if (entry.entryKind == IClasspathEntry.CPE_CONTAINER) { val container = JavaCore.getClasspathContainer(entry.path, javaProject) if (container != null && container.kind == IClasspathContainer.K_DEFAULT_SYSTEM) { return@mapNotNull container } } null } .flatMap { it.classpathEntries.toList() } .flatMap { ProjectUtils.getFileByEntry(it, javaProject) } .forEach { addToClasspath(it) } } } } private fun URL.toFile() = try { File(toURI().schemeSpecificPart) } catch (e: java.net.URISyntaxException) { if (protocol != "file") null else File(file) } private fun classpathFromClassloader(classLoader: ClassLoader): List { return when (classLoader) { is URLClassLoader -> { classLoader.urLs ?.mapNotNull { it.toFile() } ?: emptyList() } is EquinoxClassLoader -> { classLoader.classpathManager.hostClasspathEntries.map { entry -> if(entry.bundleFile.baseFile.isFile) { entry.bundleFile.baseFile } else { entry.bundleFile.baseFile.resolve("bin") } } } else -> { KotlinLogger.logWarning("Could not get dependencies from $classLoader for script provider") emptyList() } } } class CliSamWithReceiverComponentContributor(val annotations: List) : StorageComponentContainerContributor { override fun registerModuleComponents(container: StorageComponentContainer, platform: TargetPlatform, moduleDescriptor: ModuleDescriptor) { if (platform.filterIsInstance().isEmpty() ) return container.useInstance(SamWithReceiverResolverExtension(annotations)) } } inline fun ComponentProvider.get(): T { return getService(T::class.java) } fun ComponentProvider.getService(request: Class): T { return tryGetService(request) ?: throw IllegalArgumentException("Unresolved service: $request") } @Suppress("UNCHECKED_CAST") fun ComponentProvider.tryGetService(request: Class): T? { return resolve(request)?.getValue() as T? } class SamWithReceiverResolverExtension( private val annotations: List ) : SamWithReceiverResolver, AnnotationBasedExtension { override fun getAnnotationFqNames(modifierListOwner: KtModifierListOwner?) = annotations override fun shouldConvertFirstSamParameterToReceiver(function: FunctionDescriptor): Boolean { return (function.containingDeclaration as? ClassDescriptor)?.hasSpecialAnnotation(null) ?: false } } class KotlinEnvironment private constructor(val eclipseProject: IProject, disposable: Disposable) : KotlinCommonEnvironment(disposable) { override val javaProject = JavaCore.create(eclipseProject) val projectCompilerProperties: KotlinProperties = KotlinProperties(ProjectScope(eclipseProject)) val compilerProperties: KotlinProperties get() = projectCompilerProperties.takeIf { it.globalsOverridden } ?: KotlinProperties.workspaceInstance val projectBuildingProperties: KotlinBuildingProperties = KotlinBuildingProperties(ProjectScope(eclipseProject)) val buildingProperties: KotlinBuildingProperties get() = projectBuildingProperties.takeIf { it.globalsOverridden } ?: KotlinBuildingProperties.workspaceInstance val index by lazy { JvmDependenciesIndexImpl(getRoots().toList()) } init { registerProjectDependenServices(javaProject) configureClasspath(javaProject) with(project) { registerService(FacadeCache::class.java, FacadeCache(project)) } registerCompilerPlugins() cachedEnvironment.putEnvironment(eclipseProject, this) } private fun registerProjectDependenServices(javaProject: IJavaProject) { val finderFactory = EclipseVirtualFileFinderFactory(javaProject) project.registerService(VirtualFileFinderFactory::class.java, finderFactory) project.registerService(MetadataFinderFactory::class.java, finderFactory) project.registerService(KotlinLightClassManager::class.java, KotlinLightClassManager(javaProject.project)) } private fun registerCompilerPlugins() { compilerProperties.compilerPlugins.entries .filter { it.active } .forEach { registerCompilerPlugin(it) } } private fun registerCompilerPlugin(it: CompilerPlugin) { val jarLoader = it.jarPath ?.replace("\$KOTLIN_HOME", ProjectUtils.ktHome) ?.let { URL("file://$it") } ?.let { URLClassLoader(arrayOf(it), this::class.java.classLoader) } val cliProcessor = jarLoader?.loadService() val registrar = jarLoader?.loadService() if (cliProcessor != null && registrar != null) { with(cliProcessor) { val configuration = CompilerConfiguration().apply { applyOptionsFrom(parseOptions(it.args), pluginOptions) } registrar.registerProjectComponents(project, configuration) } } } private inline fun ClassLoader.loadService(): T? = ServiceLoader.load(T::class.java, this) .singleOrNull { it::class.java.classLoader == this } private fun parseOptions(args: List): Map> = args.asSequence() .map { parsePluginOption("plugin:$it") } .filterNotNull() .groupBy(CliOptionValue::optionName, CliOptionValue::value) private fun configureClasspath(javaProject: IJavaProject) { if (!javaProject.exists()) return val tempFiles = try { ProjectUtils.collectClasspathWithDependenciesForBuild(javaProject) } catch (e: DependencyResolverException) { hasError = true e.resolvedFiles e.resolvedFiles } tempFiles.forEach(::addToClasspath) } companion object { private val cachedEnvironment = CachedEnvironment() private val environmentCreation = { eclipseProject: IProject -> KotlinEnvironment(eclipseProject, Disposer.newDisposable("Project Env ${eclipseProject.name}")) } @JvmStatic fun getEnvironment(eclipseProject: IProject): KotlinEnvironment = cachedEnvironment.getOrCreateEnvironment(eclipseProject, environmentCreation) @JvmStatic fun removeEnvironment(eclipseProject: IProject) { cachedEnvironment.removeEnvironment(eclipseProject) KotlinPsiManager.invalidateCachedProjectSourceFiles() KotlinAnalysisFileCache.resetCache() KotlinAnalysisProjectCache.resetCache(eclipseProject) } fun removeEnvironmentIf(check: (KotlinCommonEnvironment) -> Boolean) { val tempRemoved = cachedEnvironment.removeEnvironmentIf(check) if(tempRemoved.isNotEmpty()) { KotlinPsiManager.invalidateCachedProjectSourceFiles() KotlinAnalysisFileCache.resetCache() for (removedPrj in tempRemoved) { KotlinAnalysisProjectCache.resetCache(removedPrj) } } } @JvmStatic fun removeAllEnvironments() { cachedEnvironment.removeAllEnvironments() KotlinPsiManager.invalidateCachedProjectSourceFiles() KotlinAnalysisFileCache.resetCache() KotlinAnalysisProjectCache.resetAllCaches() } @JvmStatic fun getJavaProject(project: Project): IProject? = cachedEnvironment.getEclipseResource(project) } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinJavaManager.kt ================================================ /******************************************************************************* * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.model import com.intellij.psi.util.PsiTreeUtil import org.eclipse.core.resources.IFolder import org.eclipse.core.resources.IProject import org.eclipse.core.runtime.Path import org.eclipse.jdt.core.* import org.eclipse.jdt.core.dom.IBinding import org.eclipse.jdt.core.dom.IMethodBinding import org.jetbrains.kotlin.core.asJava.equalsJvmSignature import org.jetbrains.kotlin.core.asJava.getTypeFqName import org.jetbrains.kotlin.core.builder.KotlinPsiManager import org.jetbrains.kotlin.core.filesystem.KotlinFileSystem import org.jetbrains.kotlin.core.log.KotlinLogger import org.jetbrains.kotlin.core.resolve.lang.java.resolver.EclipseJavaSourceElement import org.jetbrains.kotlin.descriptors.SourceElement import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.source.KotlinSourceElement object KotlinJavaManager { @JvmField val KOTLIN_BIN_FOLDER: Path = Path("kotlin_bin") fun getKotlinBinFolderFor(project: IProject): IFolder = project.getFolder(KOTLIN_BIN_FOLDER) fun findEclipseType(jetClass: KtClassOrObject, javaProject: IJavaProject): IType? { return jetClass.fqName.let { if (it != null) javaProject.findType(it.asString()) else null } } fun findEclipseMembers(declaration: KtDeclaration, javaProject: IJavaProject, klass: Class): List { val containingElement = PsiTreeUtil.getParentOfType(declaration, KtClassOrObject::class.java, KtFile::class.java) val seekInParent: Boolean = containingElement is KtObjectDeclaration && containingElement.isCompanion() if (containingElement == null) return emptyList() val declaringTypeFqName = getTypeFqName(containingElement) ?: return emptyList() val eclipseType = javaProject.findType(declaringTypeFqName.asString()) ?: return emptyList() val typeMembers = findMembersIn(eclipseType, declaration, klass) return if (seekInParent) { val parentMembers = findMembersIn(eclipseType.declaringType, declaration, klass) typeMembers + parentMembers } else { typeMembers } } fun hasLinkedKotlinBinFolder(project: IProject): Boolean { val folder = project.getFolder(KOTLIN_BIN_FOLDER) return folder.isLinked && KotlinFileSystem.SCHEME == folder.locationURI.scheme } private fun findMembersIn(eclipseType: IType, declaration: KtDeclaration, klass: Class): List { fun check(member: IMember): Boolean { return klass.isAssignableFrom(member.javaClass) && equalsJvmSignature(declaration, member) } val methods = eclipseType.methods.filter { check(it) } val fields = eclipseType.fields.filter { check(it) } return methods + fields } } fun KtElement.toLightElements(): List { val javaProject = KotlinPsiManager.getJavaProject(this) if (javaProject == null) { KotlinLogger.logWarning("Cannot resolve jetElement ($this) to light elements: there is no corresponding java project") return emptyList() } if (!javaProject.isOpen) { return emptyList() } return when (this) { is KtClassOrObject -> KotlinJavaManager.findEclipseType(this, javaProject)?.let(::listOf) ?: emptyList() is KtNamedFunction, is KtSecondaryConstructor, is KtPrimaryConstructor, is KtPropertyAccessor -> KotlinJavaManager.findEclipseMembers(this as KtDeclaration, javaProject, IMethod::class.java) is KtProperty -> { val list = KotlinJavaManager.findEclipseMembers(this, javaProject, IMember::class.java) val getterList = getter?.toLightElements() ?: emptyList() val setterList = setter?.toLightElements() ?: emptyList() list + getterList + setterList } else -> emptyList() } } fun SourceElement.toJavaElements(): List { return when (this) { is EclipseJavaSourceElement -> obtainJavaElement(elementBinding)?.let(::listOf) ?: emptyList() is KotlinSourceElement -> psi.toLightElements() else -> emptyList() } } fun sourceElementsToLightElements(sourceElements: List): List { return sourceElements.flatMap { it.toJavaElements() } } private fun obtainJavaElement(binding: IBinding): IJavaElement? { return if (binding is IMethodBinding && binding.isDefaultConstructor) { binding.declaringClass.javaElement } else { binding.javaElement } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinLightVirtualFile.kt ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.model import com.intellij.testFramework.LightVirtualFile import org.jetbrains.kotlin.idea.KotlinLanguage import org.eclipse.core.resources.IFile public class KotlinLightVirtualFile(file: IFile, text: String) : LightVirtualFile(file.getName(), KotlinLanguage.INSTANCE, text) { private val path = file.getRawLocation().toOSString() override fun getPath(): String = path } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinNature.kt ================================================ /******************************************************************************* * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.model import org.eclipse.core.resources.* import org.eclipse.core.runtime.IProgressMonitor import org.eclipse.core.runtime.IStatus import org.eclipse.core.runtime.Status import org.eclipse.core.runtime.jobs.Job import org.eclipse.jdt.core.JavaCore import org.jetbrains.kotlin.core.builder.KotlinPsiManager import org.jetbrains.kotlin.core.preferences.KotlinCodeStyleProperties import java.util.* import kotlin.properties.Delegates class KotlinNature : IProjectNature { companion object { val KOTLIN_NATURE: String = "org.jetbrains.kotlin.core.kotlinNature" @JvmField val KOTLIN_BUILDER: String = "org.jetbrains.kotlin.ui.kotlinBuilder" @JvmStatic fun hasKotlinNature(project: IProject): Boolean { return project.hasNature(KOTLIN_NATURE) } @JvmStatic fun hasKotlinBuilder(project: IProject): Boolean { if (!project.isAccessible) return false return project.description.buildSpec.any { KOTLIN_BUILDER == it.builderName } } @JvmStatic fun addNature(project: IProject) { if (hasKotlinNature(project)) return project.modifyDescription { natureIds += KOTLIN_NATURE } } fun removeNature(project: IProject) { if (!hasKotlinNature(project)) return project.modifyDescription { natureIds = natureIds.filterNot { it == KOTLIN_NATURE }.toTypedArray() } } private fun IProject.modifyDescription(operation: IProjectDescription.() -> Unit) { description.apply(operation) .also { setDescription(it, null) } } } var eclipseProject: IProject by Delegates.notNull() override fun configure() { addKotlinBuilder(eclipseProject) setPreferredCodeStyle(eclipseProject) } override fun deconfigure() { removeKotlinBuilder(eclipseProject) KotlinPsiManager.removeProjectFromManager(eclipseProject) KotlinAnalysisFileCache.resetCache() KotlinAnalysisProjectCache.resetCache(eclipseProject) } override fun setProject(project: IProject) { eclipseProject = project } override fun getProject(): IProject = eclipseProject private fun addKotlinBuilder(project: IProject) { if (!hasKotlinBuilder(project)) { val description = project.description val kotlinBuilderCommand = description.newCommand().apply { builderName = KOTLIN_BUILDER } val newBuildCommands = description.buildSpec.toCollection(LinkedList()) newBuildCommands.addFirst(kotlinBuilderCommand) description.buildSpec = newBuildCommands.toTypedArray() project.setDescription(description, null) } } private fun setPreferredCodeStyle(eclipseProject: IProject) { KotlinCodeStyleProperties(ProjectScope(eclipseProject)).apply { codeStyleId = "KOTLIN_OFFICIAL" globalsOverridden = true saveChanges() } } private fun removeKotlinBuilder(project: IProject) { if (hasKotlinBuilder(project)) { val description = project.description val newBuildCommands = description.buildSpec.filter { it.builderName != KotlinNature.KOTLIN_BUILDER } description.buildSpec = newBuildCommands.toTypedArray() project.setDescription(description, null) } } } // Place Kotlin Builder before Java Builder to avoid red code in Java about Kotlin references fun setKotlinBuilderBeforeJavaBuilder(project: IProject) { val job = object : Job("Swap Kotlin builder with Java Builder") { override fun run(monitor: IProgressMonitor?): IStatus? { val description = project.description val builders = description.buildSpec.toCollection(LinkedList()) val kotlinBuilderIndex = builders.indexOfFirst { it.builderName == KotlinNature.KOTLIN_BUILDER } val javaBuilderIndex = builders.indexOfFirst { it.builderName == JavaCore.BUILDER_ID } if (kotlinBuilderIndex >= 0 && javaBuilderIndex >= 0 && javaBuilderIndex < kotlinBuilderIndex) { Collections.swap(builders, kotlinBuilderIndex, javaBuilderIndex) description.buildSpec = builders.toTypedArray() project.setDescription(description, monitor) } return Status.OK_STATUS } } job.rule = ResourcesPlugin.getWorkspace().root job.schedule() } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/KotlinRefreshProjectListener.kt ================================================ package org.jetbrains.kotlin.core.model import org.eclipse.core.resources.IProject import org.eclipse.core.resources.IResource import org.eclipse.core.resources.IResourceChangeEvent import org.eclipse.core.resources.IResourceChangeListener import org.jetbrains.kotlin.core.asJava.KotlinLightClassGeneration public object KotlinRefreshProjectListener : IResourceChangeListener { override fun resourceChanged(event: IResourceChangeEvent) { if (event.type == IResourceChangeEvent.PRE_REFRESH) { val delta = event.getDelta() if (delta == null) { tryUpdateLightClassesFor(event.resource) return } delta.accept { visitorDelta -> val resource = visitorDelta.getResource() if (resource is IProject) { tryUpdateLightClassesFor(resource) return@accept false } true } } } private fun tryUpdateLightClassesFor(resource: IResource?) { if (resource is IProject && KotlinNature.hasKotlinNature(resource)) { KotlinLightClassGeneration.updateLightClasses(resource, emptySet(), true) } } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/executableEP.kt ================================================ /******************************************************************************* * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.model import org.eclipse.core.runtime.CoreException import org.eclipse.core.runtime.IConfigurationElement import org.eclipse.core.runtime.Platform import org.jetbrains.kotlin.core.log.KotlinLogger import kotlin.reflect.KClass import kotlin.reflect.KProperty fun loadExecutableEP(extensionPointId: String, isCaching: Boolean = false): List> { return Platform .getExtensionRegistry() .getConfigurationElementsFor(extensionPointId) .map { ExecutableExtensionPointDescriptor(it, isCaching) } } class ExecutableExtensionPointDescriptor( private val configurationElement: IConfigurationElement, private val isCaching: Boolean = false ) { companion object { private const val CLASS = "class" } private var cachedProvider: T? = null val attributes: Map = configurationElement.run { attributeNames .map { it to getAttribute(it) } .toMap() } @Suppress("UNCHECKED_CAST") fun createProvider(): T? { return cachedProvider ?: try { val provider = (configurationElement.createExecutableExtension(CLASS) as T?) if (isCaching) { cachedProvider = provider } provider } catch(e: CoreException) { KotlinLogger.logError(e) null } } fun providedClass(): KClass? = configurationElement.getAttribute(CLASS)?.let { Class.forName(it).kotlin } } object EPAttribute { operator fun getValue(thisRef: ExecutableExtensionPointDescriptor<*>, property: KProperty<*>): String? = thisRef.attributes[property.name] } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/kotlinModelUtils.kt ================================================ /******************************************************************************* * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.model import org.eclipse.core.resources.IProject import org.eclipse.core.runtime.IProgressMonitor import org.eclipse.core.runtime.IStatus import org.eclipse.core.runtime.jobs.IJobChangeEvent import org.eclipse.core.runtime.jobs.Job import org.eclipse.core.runtime.jobs.JobChangeAdapter import org.eclipse.jdt.core.IJavaProject import org.jetbrains.kotlin.core.KotlinClasspathContainer import org.jetbrains.kotlin.core.utils.ProjectUtils import org.eclipse.core.resources.ResourcesPlugin fun unconfigureKotlinProject(javaProject: IJavaProject) { val project = javaProject.getProject() unconfigureKotlinNature(project) unconfigureKotlinRuntime(javaProject) removeKotlinBinFolder(project) } fun unconfigureKotlinNature(project: IProject) { if (KotlinNature.hasKotlinNature(project)) { val description = project.getDescription() val newNatures = description.getNatureIds().filter { it != KotlinNature.KOTLIN_NATURE } description.setNatureIds(newNatures.toTypedArray()) project.setDescription(description, null) } } fun unconfigureKotlinRuntime(javaProject: IJavaProject) { if (ProjectUtils.hasKotlinRuntime(javaProject.getProject())) { val newEntries = javaProject.getRawClasspath().filterNot { ProjectUtils.equalsEntriesPaths(it, KotlinClasspathContainer.CONTAINER_ENTRY) } javaProject.setRawClasspath(newEntries.toTypedArray(), null) } } fun removeKotlinBinFolder(project: IProject) { val kotlinBinFolder = KotlinJavaManager.getKotlinBinFolderFor(project) kotlinBinFolder.delete(true, null) } fun canBeDeconfigured(project: IProject): Boolean { return when { KotlinNature.hasKotlinNature(project) || ProjectUtils.hasKotlinRuntime(project) -> true else -> false } } fun isConfigurationMissing(project: IProject): Boolean { return when { !KotlinNature.hasKotlinNature(project) || !ProjectUtils.hasKotlinRuntime(project) -> true else -> false } } fun runJob(name: String, priority: Int = Job.LONG, action: (IProgressMonitor) -> IStatus) { runJob(name, priority, null, action, {}) } fun runJob( name: String, priority: Int = Job.LONG, jobFamily: Any? = null, action: (IProgressMonitor) -> IStatus, postTask: (IJobChangeEvent) -> Unit ): Job { val job = object : Job(name) { override fun run(monitor: IProgressMonitor): IStatus { return action(monitor) } override fun belongsTo(family: Any?): Boolean { return jobFamily?.equals(family) ?: super.belongsTo(family) } } job.setPriority(priority) job.setRule(ResourcesPlugin.getWorkspace().getRoot()); job.addJobChangeListener(object : JobChangeAdapter() { override fun done(event: IJobChangeEvent) { postTask(event) } }) job.schedule() return job } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/preferences/KotlinBuildingProperties.kt ================================================ package org.jetbrains.kotlin.core.preferences import org.eclipse.core.runtime.preferences.IScopeContext import org.eclipse.core.runtime.preferences.InstanceScope import org.jetbrains.kotlin.core.Activator class KotlinBuildingProperties(scope: IScopeContext = InstanceScope.INSTANCE) : Preferences(scope, Activator.PLUGIN_ID) { var globalsOverridden by BooleanPreference() var useIncremental by BooleanPreference() companion object { val workspaceInstance by lazy { KotlinBuildingProperties() } } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/preferences/KotlinCodeStyleProperties.kt ================================================ package org.jetbrains.kotlin.core.preferences import org.eclipse.core.resources.ProjectScope import org.eclipse.core.runtime.preferences.IScopeContext import org.eclipse.core.runtime.preferences.InstanceScope import org.jetbrains.kotlin.core.Activator import org.jetbrains.kotlin.core.builder.KotlinPsiManager import org.jetbrains.kotlin.core.formatting.KotlinCodeStyleManager import org.jetbrains.kotlin.idea.formatter.KotlinPredefinedCodeStyle import org.jetbrains.kotlin.idea.formatter.KotlinStyleGuideCodeStyle import org.jetbrains.kotlin.psi.KtFile class KotlinCodeStyleProperties(scope: IScopeContext = InstanceScope.INSTANCE) : Preferences(scope, "${Activator.PLUGIN_ID}/codeStyle" ) { var globalsOverridden by BooleanPreference() var codeStyleId by StringPreference() companion object { val workspaceInstance by lazy { KotlinCodeStyleProperties() } } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/preferences/KotlinProperties.kt ================================================ package org.jetbrains.kotlin.core.preferences import org.eclipse.core.runtime.preferences.DefaultScope import org.eclipse.core.runtime.preferences.IScopeContext import org.eclipse.core.runtime.preferences.InstanceScope import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.config.LanguageVersion import org.jetbrains.kotlin.core.Activator import org.osgi.service.prefs.Preferences as InternalPreferences class KotlinProperties(scope: IScopeContext = InstanceScope.INSTANCE) : Preferences(scope, Activator.PLUGIN_ID) { var globalsOverridden by BooleanPreference() // Note: default value is defined in preferences.ini var jvmTarget by object : Preference { override fun reader(text: String?) = text?.let { enumValueOf(it) } ?: JvmTarget.DEFAULT override fun writer(value: JvmTarget) = value.name } var languageVersion by object : Preference { override fun reader(text: String?) = text ?.let { LanguageVersion.fromVersionString(it) } ?: LanguageVersion.LATEST_STABLE override fun writer(value: LanguageVersion) = value.versionString } var apiVersion by object : Preference { override fun reader(text: String?): ApiVersion { val apiVersionByLanguageVersion = ApiVersion.createByLanguageVersion(languageVersion) return text?.let { ApiVersion.parse(it) } ?.takeIf { it <= apiVersionByLanguageVersion } ?: apiVersionByLanguageVersion } override fun writer(value: ApiVersion) = value.versionString } var jdkHome by StringPreference() val compilerPlugins by ChildCollection(::CompilerPlugin) var compilerFlags by StringPreference() fun isJDKHomUndefined() = jdkHome.isNullOrBlank() companion object { // Property object in instance scope (workspace) must be created after init() val workspaceInstance by lazy { KotlinProperties() } @JvmStatic fun init() { // Ensure 'preferences.ini' are loaded DefaultScope.INSTANCE.getNode(Activator.PLUGIN_ID) } } } class CompilerPlugin(scope: IScopeContext, path: String) : Preferences(scope, path) { var jarPath by StringPreference() var args by ListPreference() var active by BooleanPreference() } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/preferences/KotlinPropertiesExtensions.kt ================================================ package org.jetbrains.kotlin.core.preferences import org.jetbrains.kotlin.config.* private enum class CompilerFlagsMapping(val flag: String, vararg val alternativeFlags: String) : (List) -> Pair, *>? { JVM_DEFAULT("-Xjvm-default") { override fun invoke(value: List): Pair, JvmDefaultMode>? { if (value.isEmpty()) return null val tempSingle = value.single() return JvmDefaultMode.fromStringOrNull(tempSingle) ?.let { JvmAnalysisFlags.jvmDefaultMode to it } } }, OPT_IN("-opt-in", "-Xopt-in") { override fun invoke(value: List): Pair, *>? { if (value.isEmpty()) return null return AnalysisFlags.optIn to value } }, USE_XR("-Xuse-ir") { override fun invoke(value: List): Pair, *>? { if (value.isEmpty()) return null val tempSingle = value.single() val tempUseIr = tempSingle.toBooleanStrictOrNull() return when { tempUseIr != null -> JvmAnalysisFlags.useIR to tempUseIr else -> null } } }; companion object { fun flagByString(flag: String) = values().firstOrNull { it.flag == flag || flag in it.alternativeFlags } } } private val KotlinProperties.analyzerCompilerFlags: Map, Any?> get() = compilerFlags?.split("\\s+".toRegex())?.mapNotNull { flagString -> flagString.split("=", limit = 2).takeIf { it.size == 2 } }?.groupBy( { (key) -> key }, { (_, value) -> value })?.mapNotNull { (key, value) -> CompilerFlagsMapping.flagByString(key)?.invoke(value) }.orEmpty().toMap() val KotlinProperties.languageVersionSettings: LanguageVersionSettings get() = LanguageVersionSettingsImpl(languageVersion, apiVersion, analyzerCompilerFlags) ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/preferences/Preferences.kt ================================================ package org.jetbrains.kotlin.core.preferences import org.eclipse.core.runtime.preferences.ConfigurationScope import org.eclipse.core.runtime.preferences.DefaultScope import org.eclipse.core.runtime.preferences.IScopeContext import org.eclipse.core.runtime.preferences.InstanceScope import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult import kotlin.properties.ReadOnlyProperty import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty import org.osgi.service.prefs.Preferences as OsgiPreferences private val SCOPES = listOf(InstanceScope.INSTANCE, ConfigurationScope.INSTANCE, DefaultScope.INSTANCE) /** * Wrapper of a preference node ([OsgiPreferences]). * Allows querying a non-existent node without creating it. */ internal open class ReadableStore(protected val scope: IScopeContext, protected val path: String) { protected var node: OsgiPreferences? = if (scope.getNode("").nodeExists(path)) scope.getNode(path) else null protected val guaranteedNode: OsgiPreferences get() = node ?: scope.getNode(path).also { node = it } val exists: Boolean get() = node != null val keysOfValues: Set get() = node?.keys()?.toSet() ?: emptySet() val keysOfChildren: Set get() = node?.childrenNames()?.toSet() ?: emptySet() fun getValue(key: String): String? = node?.get(key, null) } /** * Extends [ReadableStore] with [setValue], [removeValue] and [deleteSelf] operations. * These operations modify the node. */ internal class WritableStore(scope: IScopeContext, path: String) : ReadableStore(scope, path) { fun setValue(key: String, value: String) { // Create node if it doesn't exist with(guaranteedNode) { put(key, value) flush() } } fun removeValue(key: String) { // Create node if it doesn't exist with(guaranteedNode) { remove(key) flush() } } fun deleteSelf() { // Create and then delete node with(guaranteedNode) { val parent = parent() removeNode() parent.flush() } node = null } } abstract class PreferencesBase(scope: IScopeContext, path: String) { internal val mainStore = WritableStore(scope, path) internal val inheritedStores = SCOPES.takeLastWhile { scope::class != it::class } .map { ReadableStore(it, path) } abstract fun loadDefaults() // Does not save changes abstract fun saveChanges() abstract fun cancelChanges() } abstract class Preferences(private val scope: IScopeContext, private val path: String) : PreferencesBase(scope, path) { val key: String = path.takeLastWhile { it != '/' } private val childPreferences: MutableList = mutableListOf() // Unsaved changes private var markedForDeletion: Boolean = !mainStore.exists private val modifiedValues: MutableMap = hashMapOf() private val removedValues: MutableSet = hashSetOf() val existsInOwnScope: Boolean get() = !markedForDeletion val keysInOwnScope: Set get() = mainStore.keysOfValues + modifiedValues.keys - removedValues val keysInParentScopes: Set get() = inheritedStores.flatMap { it.keysOfValues }.toSet() val keys: Set get() = keysInOwnScope + keysInParentScopes // Does not save changes fun getValue(key: String): String? = when (key) { in modifiedValues -> modifiedValues[key] in removedValues -> null else -> mainStore.getValue(key) } ?: inheritedStores.firstNotNullOfOrNull { it.getValue(key) } // Does not save changes fun setValue(key: String, value: String) { removedValues -= key modifiedValues[key] = value markedForDeletion = false } // Does not save changes fun removeValue(key: String) { modifiedValues -= key removedValues += key markedForDeletion = false } // Does not save changes override fun loadDefaults() { modifiedValues.clear() removedValues.clear() removedValues += mainStore.keysOfValues markedForDeletion = false childPreferences.forEach { it.loadDefaults() } } // Does not save changes fun delete() { loadDefaults() markedForDeletion = true } override fun saveChanges() { if (markedForDeletion) { mainStore.deleteSelf() } else { modifiedValues.forEach { key, value -> mainStore.setValue(key, value) } removedValues.forEach { key -> mainStore.removeValue(key) } childPreferences.forEach { it.saveChanges() } } modifiedValues.clear() removedValues.clear() } override fun cancelChanges() { modifiedValues.clear() removedValues.clear() markedForDeletion = !mainStore.exists childPreferences.forEach { it.cancelChanges() } } protected interface Preference : ReadWriteProperty { fun reader(text: String?): T fun writer(value: T): String? override operator fun getValue(thisRef: Preferences, property: KProperty<*>): T = thisRef.getValue(property.name).let(::reader) override operator fun setValue(thisRef: Preferences, property: KProperty<*>, value: T) = writer(value).let { if (it != null) thisRef.setValue(property.name, it) else thisRef.removeValue(property.name) } } protected class StringPreference : Preference { override fun reader(text: String?) = text override fun writer(value: String?) = value } protected class BooleanPreference : Preference { override fun reader(text: String?) = text?.toBoolean() ?: false override fun writer(value: Boolean) = value.toString() } protected class ListPreference(val separator: String = "|") : Preference> { override fun reader(text: String?) = text?.split(separator)?.filter(String::isNotEmpty) ?: listOf() override fun writer(value: List) = value.joinToString(separator) } protected inline fun > EnumPreference(defaultValue: T): ReadWriteProperty = object : Preference { override fun reader(text: String?) = text?.let { enumValueOf(it) } ?: defaultValue override fun writer(value: T) = value.name } protected class ChildCollection(val factory: (IScopeContext, String) -> T) { operator fun provideDelegate(thisRef: Preferences, property: KProperty<*>) = object : ReadOnlyProperty> { val instance by lazy { PreferencesCollection(thisRef.scope, "${thisRef.path}/${property.name}", factory) .also { thisRef.childPreferences.add(it) } } override fun getValue(thisRef: Preferences, property: KProperty<*>): PreferencesCollection = instance } } } class PreferencesCollection( private val scope: IScopeContext, private val path: String, private val elementFactory: (IScopeContext, String) -> T ) : PreferencesBase(scope, path) { private val cache = mutableMapOf() val entries: List get() = keys.map { get(it) } private val keysInOwnScope: Set get() = mainStore.keysOfChildren + cache.keys - cache.filterValues { !it.existsInOwnScope }.keys private val keysInParentScopes: Set get() = inheritedStores.flatMap { it.keysOfChildren }.toSet() private val keys: Set get() = keysInOwnScope + keysInParentScopes private fun makeCache(key: String): T = cache.getOrPut(key) { elementFactory(scope, "$path/$key") } operator fun contains(key: String): Boolean = key in keys operator fun get(key: String): T = makeCache(key) // Does not save changes override fun loadDefaults() { cache.clear() entries.forEach { it.delete() } } override fun saveChanges() { cache.values.forEach { it.saveChanges() } } override fun cancelChanges() { cache.clear() } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/references/KotlinReference.kt ================================================ /******************************************************************************* * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.references import com.intellij.util.SmartList import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getParentOfType import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall import org.jetbrains.kotlin.resolve.calls.util.getCall import org.jetbrains.kotlin.resolve.calls.util.getResolvedCall import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.utils.addIfNotNull inline private fun ArrayList>.register( e: KtElement, action: (T) -> KotlinReference ) { if (e is T) this.add(action(e)) } inline private fun ArrayList>.registerMulti( e: KtElement, action: (T) -> List> ) { if (e is T) this.addAll(action(e)) } public fun createReferences(element: KtElement): List> { return arrayListOf>().apply { register(element, ::KotlinSimpleNameReference) register(element, ::KotlinInvokeFunctionReference) register(element, ::KotlinConstructorDelegationReference) registerMulti(element) { if (it.getReferencedNameElementType() != KtTokens.IDENTIFIER) return@registerMulti emptyList() when (it.readWriteAccess()) { ReferenceAccess.READ -> listOf(KotlinSyntheticPropertyAccessorReference.Getter(it)) ReferenceAccess.WRITE -> listOf(KotlinSyntheticPropertyAccessorReference.Setter(it)) ReferenceAccess.READ_WRITE -> listOf( KotlinSyntheticPropertyAccessorReference.Getter(it), KotlinSyntheticPropertyAccessorReference.Setter(it) ) } } register(element, ::KotlinReferenceExpressionReference) register(element, ::KotlinKtPropertyDelegateReference) } } public interface KotlinReference { val expression: KtElement fun getTargetDescriptors(context: BindingContext): Collection val resolvesByNames: Collection } class KotlinKtPropertyDelegateReference(override val expression: KtPropertyDelegate) : KotlinReference { override fun getTargetDescriptors(context: BindingContext): Collection { val tempProperty = expression.getParentOfType(false) ?: return emptyList() val tempDescriptor = tempProperty.resolveToDescriptorIfAny() as? VariableDescriptorWithAccessors ?: return emptyList() val tempProviderDescriptor = context[BindingContext.PROVIDE_DELEGATE_RESOLVED_CALL, tempDescriptor]?.candidateDescriptor val tempGetDescriptor = tempDescriptor.getter?.let { context[BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, it]?.candidateDescriptor } val tempSetDescriptor = tempDescriptor.setter?.let { context[BindingContext.DELEGATED_PROPERTY_RESOLVED_CALL, it]?.candidateDescriptor } return listOfNotNull(tempProviderDescriptor, tempGetDescriptor, tempSetDescriptor) } override val resolvesByNames: Collection get() = emptyList() } open class KotlinSimpleNameReference(override val expression: KtSimpleNameExpression) : KotlinReference { override fun getTargetDescriptors(context: BindingContext): Collection { return expression.getReferenceTargets(context) } override val resolvesByNames: Collection get() { val element = expression if (element is KtOperationReferenceExpression) { val tokenType = element.operationSignTokenType if (tokenType != null) { val name = OperatorConventions.getNameForOperationSymbol( tokenType, element.parent is KtUnaryExpression, element.parent is KtBinaryExpression ) ?: return emptyList() val counterpart = OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS[tokenType] return if (counterpart != null) { val counterpartName = OperatorConventions.getNameForOperationSymbol(counterpart, false, true)!! listOf(name, counterpartName) } else { listOf(name) } } } return listOf(element.getReferencedNameAsName()) } } public class KotlinInvokeFunctionReference(override val expression: KtCallExpression) : KotlinReference { override val resolvesByNames: Collection get() = listOf(OperatorNameConventions.INVOKE) override fun getTargetDescriptors(context: BindingContext): Collection { val call = expression.getCall(context) val resolvedCall = call.getResolvedCall(context) return when { resolvedCall is VariableAsFunctionResolvedCall -> listOf(resolvedCall.functionCall.getCandidateDescriptor()) call != null && resolvedCall != null && call.getCallType() == Call.CallType.INVOKE -> listOf(resolvedCall.getCandidateDescriptor()) else -> emptyList() } } } sealed class KotlinSyntheticPropertyAccessorReference( expression: KtNameReferenceExpression, private val getter: Boolean ) : KotlinSimpleNameReference(expression) { override fun getTargetDescriptors(context: BindingContext): Collection { val descriptors = super.getTargetDescriptors(context) if (descriptors.none { it is SyntheticJavaPropertyDescriptor }) return emptyList() val result = SmartList() for (descriptor in descriptors) { if (descriptor is SyntheticJavaPropertyDescriptor) { if (getter) { result.add(descriptor.getMethod) } else { result.addIfNotNull(descriptor.setMethod) } } } return result } override val resolvesByNames: Collection get() = listOf(expression.getReferencedNameAsName()) class Getter(expression: KtNameReferenceExpression) : KotlinSyntheticPropertyAccessorReference(expression, true) class Setter(expression: KtNameReferenceExpression) : KotlinSyntheticPropertyAccessorReference(expression, false) } public class KotlinConstructorDelegationReference(override val expression: KtConstructorDelegationReferenceExpression) : KotlinReference { override fun getTargetDescriptors(context: BindingContext) = expression.getReferenceTargets(context) override val resolvesByNames: Collection get() = emptyList() } class KotlinReferenceExpressionReference(override val expression: KtReferenceExpression) : KotlinReference { override fun getTargetDescriptors(context: BindingContext): Collection { return expression.getReferenceTargets(context) } override val resolvesByNames: Collection get() = emptyList() } fun KtReferenceExpression.getReferenceTargets(context: BindingContext): Collection { val targetDescriptor = context[BindingContext.REFERENCE_TARGET, this] return if (targetDescriptor != null) { listOf(targetDescriptor) } else { context[BindingContext.AMBIGUOUS_REFERENCE_TARGET, this].orEmpty() } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/references/referenceUtils.kt ================================================ /******************************************************************************* * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.references import com.intellij.openapi.util.Key import com.intellij.psi.PsiElement import com.intellij.psi.util.PsiTreeUtil import org.eclipse.jdt.core.IJavaProject import org.eclipse.jdt.core.JavaCore import org.jetbrains.kotlin.core.builder.KotlinPsiManager import org.jetbrains.kotlin.core.resolve.EclipseDescriptorUtils import org.jetbrains.kotlin.core.resolve.KotlinAnalyzer import org.jetbrains.kotlin.core.utils.getBindingContext import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.SourceElement import org.jetbrains.kotlin.descriptors.VariableDescriptorWithAccessors import org.jetbrains.kotlin.descriptors.accessors import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny import org.jetbrains.kotlin.idea.imports.canBeReferencedViaImport import org.jetbrains.kotlin.idea.util.CallTypeAndReceiver import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getAssignmentByLHS import org.jetbrains.kotlin.psi.psiUtil.getParentOfType import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension import org.jetbrains.kotlin.resolve.source.KotlinSourceElement import org.jetbrains.kotlin.utils.addToStdlib.constant val FILE_PROJECT: Key = Key.create("FILE_PROJECT") fun List>.resolveToSourceElements(ktFile: KtFile): List { if (isEmpty()) return emptyList() val javaProject = JavaCore.create(KotlinPsiManager.getEclipseFile(ktFile)?.project) ?: ktFile.getUserData(FILE_PROJECT) ?: return emptyList() return resolveToSourceElements(ktFile.getBindingContext(), javaProject) } fun List>.resolveToSourceElements( context: BindingContext, javaProject: IJavaProject ): List { return flatMap { it.getTargetDescriptors(context) } .flatMap { EclipseDescriptorUtils.descriptorToDeclarations(it, javaProject.project) } } fun getReferenceExpression(element: PsiElement): KtReferenceExpression? { return PsiTreeUtil.getNonStrictParentOfType(element, KtReferenceExpression::class.java) } fun KtElement.resolveToSourceDeclaration(): List { return when (val jetElement = this) { is KtDeclaration -> listOf(KotlinSourceElement(jetElement)) else -> { // Try search declaration by reference val referenceExpression = getReferenceExpression(jetElement) ?: jetElement val reference = createReferences(referenceExpression) reference.resolveToSourceElements(jetElement.containingKtFile) } } } enum class ReferenceAccess(val isRead: Boolean, val isWrite: Boolean) { READ(true, false), WRITE(false, true), READ_WRITE(true, true) } fun KtExpression.readWriteAccess(): ReferenceAccess { var expression = getQualifiedExpressionForSelectorOrThis() loop@ while (true) { when (val parent = expression.parent) { is KtParenthesizedExpression, is KtAnnotatedExpression, is KtLabeledExpression -> expression = parent as KtExpression else -> break@loop } } val assignment = expression.getAssignmentByLHS() if (assignment != null) { return when (assignment.operationToken) { KtTokens.EQ -> ReferenceAccess.WRITE else -> ReferenceAccess.READ_WRITE } } return if ((expression.parent as? KtUnaryExpression)?.operationToken in constant { setOf( KtTokens.PLUSPLUS, KtTokens.MINUSMINUS ) }) ReferenceAccess.READ_WRITE else ReferenceAccess.READ } // TODO: obtain this function from referenceUtil.kt (org.jetbrains.kotlin.idea.references) fun KotlinReference<*>.canBeResolvedViaImport(target: DeclarationDescriptor): Boolean { if (!target.canBeReferencedViaImport()) return false if (target.isExtension) return true // assume that any type of reference can use imports when resolved to extension val referenceExpression = this.expression as? KtNameReferenceExpression ?: return false if (CallTypeAndReceiver.detect(referenceExpression).receiver != null) return false if (expression.parent is KtThisExpression || expression.parent is KtSuperExpression) return false // TODO: it's a bad design of PSI tree, we should change it return true } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/BuiltInsReferenceResolver.java ================================================ /* * Copyright 2010-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jetbrains.kotlin.core.resolve; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiManager; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.io.URLUtil; import kotlin.collections.CollectionsKt; import org.eclipse.core.resources.IProject; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.analyzer.common.CommonPlatformAnalyzerServices; import org.jetbrains.kotlin.builtins.DefaultBuiltIns; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.builtins.StandardNames; import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl; import org.jetbrains.kotlin.container.DslKt; import org.jetbrains.kotlin.container.StorageComponentContainer; import org.jetbrains.kotlin.context.ContextKt; import org.jetbrains.kotlin.context.MutableModuleContext; import org.jetbrains.kotlin.core.model.KotlinEnvironment; import org.jetbrains.kotlin.core.utils.ProjectUtils; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.frontend.di.InjectionKt; import org.jetbrains.kotlin.name.ClassId; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.platform.CommonPlatforms; import org.jetbrains.kotlin.psi.KtFile; import org.jetbrains.kotlin.renderer.DescriptorRenderer; import org.jetbrains.kotlin.resolve.BindingTraceContext; import org.jetbrains.kotlin.resolve.CompilerEnvironment; import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt; import org.jetbrains.kotlin.resolve.lazy.ResolveSession; import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory; import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter; import org.jetbrains.kotlin.resolve.scopes.MemberScope; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.*; public class BuiltInsReferenceResolver { private static final String RUNTIME_SRC_DIR = "jar:file:"+ ProjectUtils.buildLibPath("kotlin-stdlib-sources")+ "!/kotlin"; private volatile ModuleDescriptor moduleDescriptor; private volatile PackageFragmentDescriptor builtinsPackageFragment = null; private final Project myProject; public BuiltInsReferenceResolver(Project project) { myProject = project; initialize(); } @NotNull public static BuiltInsReferenceResolver getInstance(@NotNull IProject eclipseProject) { Project ideaProject = KotlinEnvironment.Companion.getEnvironment(eclipseProject).getProject(); return ServiceManager.getService(ideaProject, BuiltInsReferenceResolver.class); } private void initialize() { if (!areSourcesExist()) { return; } Set jetBuiltInsFiles = getBuiltInSourceFiles(); //if the sources are present, then the value cannot be null assert (jetBuiltInsFiles != null); Map, Object> tempCapabilities = Collections.emptyMap(); MutableModuleContext newModuleContext = ContextKt.ContextForNewModule( ContextKt.ProjectContext(myProject, "Context for built-ins resolver module"), Name.special(""), DefaultBuiltIns.getInstance(), null, tempCapabilities); newModuleContext.setDependencies(newModuleContext.getModule()); StorageComponentContainer container = InjectionKt.createContainerForLazyResolve( newModuleContext, new FileBasedDeclarationProviderFactory(newModuleContext.getStorageManager(), jetBuiltInsFiles), new BindingTraceContext(), CommonPlatforms.INSTANCE.getDefaultCommonPlatform(), CommonPlatformAnalyzerServices.INSTANCE, CompilerEnvironment.INSTANCE, LanguageVersionSettingsImpl.DEFAULT); ResolveSession resolveSession = DslKt.getService(container, ResolveSession.class); newModuleContext.initializeModuleContents(resolveSession.getPackageFragmentProvider()); PackageViewDescriptor packageView = newModuleContext.getModule().getPackage( StandardNames.BUILT_INS_PACKAGE_FQ_NAME); List fragments = packageView.getFragments(); moduleDescriptor = newModuleContext.getModule(); builtinsPackageFragment = CollectionsKt.single(fragments); } @Nullable private Set getBuiltInSourceFiles() { URL url; try { url = new URL(RUNTIME_SRC_DIR); } catch (MalformedURLException e) { return null; } VirtualFile vf = getSourceVirtualFile(); assert vf != null : "Virtual file not found by URL: " + url; PsiDirectory psiDirectory = PsiManager.getInstance(myProject).findDirectory(vf); assert psiDirectory != null : "No PsiDirectory for " + vf; return new HashSet(ContainerUtil.mapNotNull(psiDirectory.getFiles(), new Function() { @Override public KtFile fun(PsiFile file) { return file instanceof KtFile ? (KtFile) file : null; } })); } @Nullable private VirtualFile getSourceVirtualFile() { URL runtimeUrl; try { runtimeUrl = new URL(RUNTIME_SRC_DIR); String fromUrl = convertPathFromURL(runtimeUrl); return VirtualFileManager.getInstance().findFileByUrl(fromUrl); } catch (MalformedURLException e) { return null; } } private boolean areSourcesExist() { return getSourceVirtualFile() != null; } //the method is a copy of com.intellij.openapi.vfs.VfsUtilCore.convertFromUrl(URL) private String convertPathFromURL(URL url) { String protocol = url.getProtocol(); String path = url.getPath(); if (protocol.equals("jar")) { if (StringUtil.startsWith(path, "file:")) { try { URL subURL = new URL(path); path = subURL.getPath(); } catch (MalformedURLException e) { //VfsBundle.message("url.parse.unhandled.exception") throw new RuntimeException("Malformed URL!", e); } } else { throw new RuntimeException(new IOException("Url Parse Error" + url.toExternalForm())); //VfsBundle.message("url.parse.error", url.toExternalForm()) } } if (SystemInfo.isWindows) { while (!path.isEmpty() && path.charAt(0) == '/') { path = path.substring(1, path.length()); } } path = URLUtil.unescapePercentSequences(path); String fromUrl = protocol + "://" + path; return fromUrl; } @Nullable private DeclarationDescriptor findCurrentDescriptorForMember(@NotNull MemberDescriptor originalDescriptor) { DeclarationDescriptor containingDeclaration = findCurrentDescriptor(originalDescriptor.getContainingDeclaration()); MemberScope memberScope = getMemberScope(containingDeclaration); if (memberScope == null) return null; String renderedOriginal = DescriptorRenderer.FQ_NAMES_IN_TYPES.render(originalDescriptor); Collection descriptors; if (originalDescriptor instanceof ConstructorDescriptor && containingDeclaration instanceof ClassDescriptor) { descriptors = ((ClassDescriptor) containingDeclaration).getConstructors(); } else { descriptors = memberScope.getContributedDescriptors(DescriptorKindFilter.ALL, MemberScope.Companion.getALL_NAME_FILTER()); } for (DeclarationDescriptor member : descriptors) { if (renderedOriginal.equals(DescriptorRenderer.FQ_NAMES_IN_TYPES.render(member))) { return member; } } return null; } @Nullable public DeclarationDescriptor findCurrentDescriptor(@NotNull DeclarationDescriptor originalDescriptor) { //if there's no sources if (moduleDescriptor == null) { return null; } if (!KotlinBuiltIns.isBuiltIn(originalDescriptor)) { return null; } if (originalDescriptor instanceof ClassDescriptor) { ClassId classId = DescriptorUtilsKt.getClassId((ClassDescriptor) originalDescriptor); if (classId == null) return null; return FindClassInModuleKt.findClassAcrossModuleDependencies(moduleDescriptor, classId); } if (originalDescriptor instanceof PackageFragmentDescriptor) { return StandardNames.BUILT_INS_PACKAGE_FQ_NAME.equals(((PackageFragmentDescriptor) originalDescriptor).getFqName()) ? builtinsPackageFragment : null; } if (originalDescriptor instanceof MemberDescriptor) { return findCurrentDescriptorForMember((MemberDescriptor) originalDescriptor); } return null; } @Nullable private static MemberScope getMemberScope(@Nullable DeclarationDescriptor parent) { if (parent instanceof ClassDescriptor) { return ((ClassDescriptor) parent).getDefaultType().getMemberScope(); } else if (parent instanceof PackageFragmentDescriptor) { return ((PackageFragmentDescriptor) parent).getMemberScope(); } else { return null; } } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/DeserializedDescriptorUtils.kt ================================================ package org.jetbrains.kotlin.core.resolve; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.descriptors.ClassDescriptor fun isDeserialized(descriptor: DeclarationDescriptor) = descriptor is DeserializedCallableMemberDescriptor || descriptor is DeserializedClassDescriptor fun getContainingClassOrPackage(descriptor: DeclarationDescriptor) = descriptor.parentsWithSelf.firstOrNull() { (it is ClassDescriptor && DescriptorUtils.isTopLevelDeclaration(it)) || it is PackageFragmentDescriptor } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/EclipseAnalyzerFacadeForJVM.kt ================================================ /******************************************************************************* * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve import com.intellij.openapi.project.Project import com.intellij.psi.PsiFileFactory import com.intellij.psi.search.GlobalSearchScope import org.eclipse.jdt.core.IJavaProject import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns import org.jetbrains.kotlin.builtins.jvm.JvmBuiltInsPackageFragmentProvider import org.jetbrains.kotlin.cli.jvm.compiler.CliBindingTrace import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl import org.jetbrains.kotlin.container.ComponentProvider import org.jetbrains.kotlin.context.ContextForNewModule import org.jetbrains.kotlin.context.MutableModuleContext import org.jetbrains.kotlin.context.ProjectContext import org.jetbrains.kotlin.core.builder.KotlinPsiManager import org.jetbrains.kotlin.core.log.KotlinLogger import org.jetbrains.kotlin.core.model.EclipseScriptDefinitionProvider import org.jetbrains.kotlin.core.model.KotlinCommonEnvironment import org.jetbrains.kotlin.core.model.KotlinEnvironment import org.jetbrains.kotlin.core.model.KotlinScriptEnvironment import org.jetbrains.kotlin.core.preferences.languageVersionSettings import org.jetbrains.kotlin.core.utils.ProjectUtils import org.jetbrains.kotlin.core.utils.asResource import org.jetbrains.kotlin.descriptors.PackageFragmentProvider import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider import org.jetbrains.kotlin.frontend.java.di.initJvmBuiltInsForTopDownAnalysis import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtension import org.jetbrains.kotlin.resolve.jvm.modules.JavaModuleResolver import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformConfigurator import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.scripting.resolve.KtFileScriptSource import org.jetbrains.kotlin.scripting.resolve.refineScriptCompilationConfiguration import org.jetbrains.kotlin.storage.StorageManager import org.jetbrains.kotlin.util.KotlinFrontEndException import kotlin.math.absoluteValue import kotlin.script.experimental.api.KotlinType import kotlin.script.experimental.api.valueOrNull import kotlin.script.experimental.util.PropertiesCollection data class AnalysisResultWithProvider(val analysisResult: AnalysisResult, val componentProvider: ComponentProvider?) { companion object { val EMPTY = AnalysisResultWithProvider(AnalysisResult.EMPTY, null) } } object EclipseAnalyzerFacadeForJVM { fun analyzeSources( environment: KotlinEnvironment, filesToAnalyze: Collection ): AnalysisResultWithProvider { val filesSet = filesToAnalyze.toSet() if (filesSet.size != filesToAnalyze.size) { KotlinLogger.logWarning("Analyzed files have duplicates") } val allFiles = LinkedHashSet(filesSet) val addedFiles = filesSet.mapNotNull { getPath(it) }.toSet() ProjectUtils.getSourceFilesWithDependencies(environment.javaProject).filterNotTo(allFiles) { getPath(it) in addedFiles } return analyzeKotlin( filesToAnalyze = filesSet, allFiles = allFiles, environment = environment, javaProject = environment.javaProject, jvmTarget = environment.compilerProperties.jvmTarget ) } fun analyzeScript( environment: KotlinScriptEnvironment, scriptFile: KtFile ): AnalysisResultWithProvider { //TODO actually take dependencies from script configuration! val javaProject = environment.javaProject/*.apply { /*tempClasspath += JavaRuntime.getDefaultVMInstall() ?.let { JavaRuntime.getLibraryLocations(it) } ?.map { JavaCore.newLibraryEntry(it.systemLibraryPath, null, null) } .orEmpty()*/ /*tempClasspath += (environment.dependencies ?.classpath.orEmpty() + environment.definitionClasspath) .map { JavaCore.newLibraryEntry(Path(it.absolutePath), null, null) }*/ val tempClasspath = environment.getRoots().mapTo(hashSetOf()) { val tempFile = it.file if(it.type == JavaRoot.RootType.SOURCE) { JavaCore.newSourceEntry(Path(tempFile.path)) } else { JavaCore.newLibraryEntry(Path(tempFile.path), null, null) } }.toTypedArray() setRawClasspath(tempClasspath, null) }*/ val allFiles = LinkedHashSet().run { add(scriptFile) environment.dependencies?.sources?.toList() .orEmpty() .mapNotNull { it.asResource } .mapNotNull { KotlinPsiManager.getKotlinParsedFile(it) } .toCollection(this) } ProjectUtils.getSourceFilesWithDependencies(environment.javaProject).toCollection(allFiles) val tempSourceCode = KtFileScriptSource(scriptFile) val tempRefinedConfig = environment.definition?.let { refineScriptCompilationConfiguration(tempSourceCode, it, environment.project) }?.valueOrNull()?.configuration val tempContribution = EclipseScriptDefinitionProvider.getContribution(tempSourceCode) val tempDefaultImports = tempRefinedConfig?.get(PropertiesCollection.Key("defaultImports", emptyList())) ?: emptyList() val tempImports = ArrayList(tempDefaultImports) val analyzerService = object : PlatformDependentAnalyzerServices() { override val defaultLowPriorityImports: List = listOf(ImportPath.fromString("java.lang.*")) override val platformConfigurator: PlatformConfigurator = JvmPlatformConfigurator override fun computePlatformSpecificDefaultImports( storageManager: StorageManager, result: MutableList ) { result.add(ImportPath.fromString("kotlin.jvm.*")) tempImports.map(ImportPath::fromString).toCollection(result) fun addAllClassifiersFromScope(scope: MemberScope) { for (descriptor in scope.getContributedDescriptors( DescriptorKindFilter.CLASSIFIERS, MemberScope.ALL_NAME_FILTER )) { result.add(ImportPath(DescriptorUtils.getFqNameSafe(descriptor), false)) } } for (builtInPackage in JvmBuiltIns( storageManager, JvmBuiltIns.Kind.FROM_CLASS_LOADER ).builtInPackagesImportedByDefault) { addAllClassifiersFromScope(builtInPackage.memberScope) } } } val tempProperties = tempRefinedConfig?.get(PropertiesCollection.Key("providedProperties", emptyMap())) if (!tempProperties.isNullOrEmpty()) { val tempPackageName = "scriptParameters${scriptFile.virtualFilePath.hashCode().absoluteValue}" val tempContent = "package $tempPackageName\n" + tempProperties.entries.joinToString(separator = "\n") { (key, value) -> val isNullable = tempContribution?.isNullable(key, tempRefinedConfig) ?: true """ |@Deprecated(message = "Do not import this explicitly! Used only in eclipse as workaround for providedProperties in Scripts!", level = DeprecationLevel.WARNING) |val $key: ${value.typeName}${if(isNullable) "? = null" else " = TODO()"} """.trimMargin("|") } tempImports.add("$tempPackageName.*") val tempKtFile = PsiFileFactory.getInstance(environment.project) .createFileFromText("scriptParameters.kt", KotlinLanguage.INSTANCE, tempContent) as? KtFile if (tempKtFile != null) { allFiles.add(tempKtFile) } } return analyzeKotlin( filesToAnalyze = listOf(scriptFile), allFiles = allFiles, environment = environment, javaProject = javaProject, analyzerService = analyzerService ) } private fun analyzeKotlin( filesToAnalyze: Collection, allFiles: Collection, environment: KotlinCommonEnvironment, javaProject: IJavaProject?, jvmTarget: JvmTarget = JvmTarget.DEFAULT, analyzerService: PlatformDependentAnalyzerServices? = null ): AnalysisResultWithProvider { val project = environment.project val moduleContext = createModuleContext(project, environment.configuration, true) val storageManager = moduleContext.storageManager val module = moduleContext.module val providerFactory = FileBasedDeclarationProviderFactory(moduleContext.storageManager, allFiles) val trace = CliBindingTrace() val sourceScope = TopDownAnalyzerFacadeForJVM.newModuleSearchScope(project, filesToAnalyze) val moduleClassResolver = TopDownAnalyzerFacadeForJVM.SourceOrBinaryModuleClassResolver(sourceScope) val languageVersionSettings = javaProject?.project?.let { KotlinEnvironment.getEnvironment(it).compilerProperties.languageVersionSettings } ?: LanguageVersionSettingsImpl( LanguageVersionSettingsImpl.DEFAULT.languageVersion, LanguageVersionSettingsImpl.DEFAULT.apiVersion ) val optionalBuiltInsModule = JvmBuiltIns(storageManager, JvmBuiltIns.Kind.FROM_CLASS_LOADER) .apply { initialize(module, true) } .builtInsModule val dependencyModule = run { val dependenciesContext = ContextForNewModule( moduleContext, Name.special( "" ), module.builtIns, null ) val dependencyScope = GlobalSearchScope.notScope(sourceScope) val dependenciesContainer = createContainerForTopDownAnalyzerForJvm( dependenciesContext, trace, DeclarationProviderFactory.EMPTY, dependencyScope, LookupTracker.DO_NOTHING, KotlinPackagePartProvider(environment), jvmTarget, languageVersionSettings, moduleClassResolver, javaProject, environment.project.getService(JavaModuleResolver::class.java), null ) moduleClassResolver.compiledCodeResolver = dependenciesContainer.get() dependenciesContext.setDependencies(listOfNotNull(dependenciesContext.module, optionalBuiltInsModule)) dependenciesContext.initializeModuleContents( CompositePackageFragmentProvider( listOf( moduleClassResolver.compiledCodeResolver.packageFragmentProvider, dependenciesContainer.get() ), "" ) ) dependenciesContext.module } val container = createContainerForTopDownAnalyzerForJvm( moduleContext, trace, providerFactory, sourceScope, LookupTracker.DO_NOTHING, KotlinPackagePartProvider(environment), jvmTarget, languageVersionSettings, moduleClassResolver, javaProject, environment.project.getService(JavaModuleResolver::class.java), analyzerService ).apply { initJvmBuiltInsForTopDownAnalysis() } moduleClassResolver.sourceCodeResolver = container.get() val additionalProviders = ArrayList() additionalProviders.add(container.get().packageFragmentProvider) PackageFragmentProviderExtension.getInstances(project).mapNotNullTo(additionalProviders) { extension -> extension.getPackageFragmentProvider(project, module, storageManager, trace, null, LookupTracker.DO_NOTHING) } module.setDependencies( listOfNotNull(module, dependencyModule, optionalBuiltInsModule), setOf(dependencyModule) ) module.initialize( CompositePackageFragmentProvider( listOf(container.get().packageFragmentProvider) + additionalProviders, "" ) ) try { container.get() .analyzeDeclarations(TopDownAnalysisMode.TopLevelDeclarations, filesToAnalyze) } catch (e: KotlinFrontEndException) { // Editor will break if we do not catch this exception // and will not be able to save content without reopening it. // In IDEA this exception throws only in CLI KotlinLogger.logError(e) } return AnalysisResultWithProvider( AnalysisResult.success(trace.bindingContext, module), container ) } private fun getPath(jetFile: KtFile): String? = jetFile.virtualFile?.path private fun createModuleContext( project: Project, configuration: CompilerConfiguration, createBuiltInsFromModule: Boolean ): MutableModuleContext { val projectContext = ProjectContext(project, "context for project ${project.name}") val builtIns = JvmBuiltIns( projectContext.storageManager, if (createBuiltInsFromModule) JvmBuiltIns.Kind.FROM_DEPENDENCIES else JvmBuiltIns.Kind.FROM_CLASS_LOADER ) return ContextForNewModule( projectContext, Name.special("<${configuration.getNotNull(CommonConfigurationKeys.MODULE_NAME)}>"), builtIns, null ).apply { if (createBuiltInsFromModule) { builtIns.builtInsModule = module } } } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/EclipseDescriptorUtils.java ================================================ package org.jetbrains.kotlin.core.resolve; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; import org.eclipse.core.resources.IProject; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor; import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind; import org.jetbrains.kotlin.descriptors.ClassDescriptor; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource; import org.jetbrains.kotlin.descriptors.SourceElement; import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils; // Note: copied with some changes from DescriptorToSourceUtils public class EclipseDescriptorUtils { // NOTE this is also used by KDoc @Nullable public static SourceElement descriptorToDeclaration(@NotNull DeclarationDescriptor descriptor) { if (descriptor instanceof CallableMemberDescriptor) { return callableDescriptorToDeclaration((CallableMemberDescriptor) descriptor); } else if (descriptor instanceof ClassDescriptor) { return classDescriptorToDeclaration((ClassDescriptor) descriptor); } else { return doGetDescriptorToDeclaration(descriptor); } } @NotNull public static List descriptorToDeclarations(@NotNull DeclarationDescriptor descriptor, @NotNull IProject project) { if (KotlinBuiltIns.isBuiltIn(descriptor)) { Collection effectiveReferencedDescriptors = DescriptorToSourceUtils.getEffectiveReferencedDescriptors(descriptor); HashSet result = new HashSet(); BuiltInsReferenceResolver resolver = BuiltInsReferenceResolver.getInstance(project); for (DeclarationDescriptor effectiveReferenced: effectiveReferencedDescriptors) { DeclarationDescriptor resultDescriptor = resolver.findCurrentDescriptor(effectiveReferenced); if (resultDescriptor != null && resultDescriptor instanceof DeclarationDescriptorWithSource) { SourceElement element = ((DeclarationDescriptorWithSource)resultDescriptor).getSource(); if (!element.equals(SourceElement.NO_SOURCE)) { result.add(element); } } } return new ArrayList(result); } //TODO: this returns a source element for containing element with existing .class file. This logic should be moved to a caller. if (DeserializedDescriptorUtilsKt.isDeserialized(descriptor)) { DeclarationDescriptor containing = DeserializedDescriptorUtilsKt.getContainingClassOrPackage(descriptor); if (containing != null) { return Arrays.asList(descriptorToDeclaration(containing)); } } if (descriptor instanceof CallableMemberDescriptor) { return callableDescriptorToDeclarations((CallableMemberDescriptor) descriptor); } else { SourceElement sourceElement = descriptorToDeclaration(descriptor); if (sourceElement != null) { return Arrays.asList(sourceElement); } else { return new ArrayList(); } } } @Nullable public static SourceElement callableDescriptorToDeclaration(@NotNull CallableMemberDescriptor callable) { if (callable.getKind() == Kind.DECLARATION || callable.getKind() == Kind.SYNTHESIZED) { return doGetDescriptorToDeclaration(callable); } //TODO: should not use this method for fake_override and delegation Collection overriddenDescriptors = callable.getOverriddenDescriptors(); if (overriddenDescriptors.size() == 1) { return callableDescriptorToDeclaration(overriddenDescriptors.iterator().next()); } return null; } @NotNull public static List callableDescriptorToDeclarations(@NotNull CallableMemberDescriptor callable) { if (callable.getKind() == Kind.DECLARATION || callable.getKind() == Kind.SYNTHESIZED) { SourceElement sourceElement = doGetDescriptorToDeclaration(callable); return sourceElement != null ? Arrays.asList(sourceElement) : Arrays.asList(); } List r = new ArrayList<>(); Collection overriddenDescriptors = callable.getOverriddenDescriptors(); for (CallableMemberDescriptor overridden : overriddenDescriptors) { r.addAll(callableDescriptorToDeclarations(overridden)); } return r; } @Nullable public static SourceElement classDescriptorToDeclaration(@NotNull ClassDescriptor clazz) { return doGetDescriptorToDeclaration(clazz); } @Nullable private static SourceElement doGetDescriptorToDeclaration(@NotNull DeclarationDescriptor descriptor) { DeclarationDescriptor original = descriptor.getOriginal(); if (!(original instanceof DeclarationDescriptorWithSource)) { return null; } return ((DeclarationDescriptorWithSource) original).getSource(); } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/KotlinAnalyzer.kt ================================================ /******************************************************************************* * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve import org.eclipse.core.resources.IProject import org.jetbrains.kotlin.core.model.KotlinAnalysisFileCache import org.jetbrains.kotlin.core.model.KotlinEnvironment import org.jetbrains.kotlin.core.model.getEnvironment import org.jetbrains.kotlin.psi.KtFile object KotlinAnalyzer { fun analyzeFile(jetFile: KtFile): AnalysisResultWithProvider { return KotlinAnalysisFileCache.getAnalysisResult(jetFile) } fun analyzeFiles(files: Collection): AnalysisResultWithProvider { return when { files.isEmpty() -> throw IllegalStateException("There should be at least one file to analyze") files.size == 1 -> analyzeFile(files.single()) else -> { val environment = getEnvironment(files.first().project) if (environment == null) { throw IllegalStateException("There is no environment for project: ${files.first().project}") } if (environment !is KotlinEnvironment) { throw IllegalStateException("Only KotlinEnvironment can be used to analyze several files") } analyzeFiles(environment, files) } } } fun analyzeProject(eclipseProject: IProject): AnalysisResultWithProvider { val environment = KotlinEnvironment.getEnvironment(eclipseProject) return analyzeFiles(environment, emptyList()) } private fun analyzeFiles(kotlinEnvironment: KotlinEnvironment, filesToAnalyze: Collection): AnalysisResultWithProvider { return EclipseAnalyzerFacadeForJVM.analyzeSources(kotlinEnvironment, filesToAnalyze) } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/KotlinCacheServiceImpl.kt ================================================ /******************************************************************************* * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement import com.intellij.psi.PsiFile import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.caches.resolve.KotlinCacheService import org.jetbrains.kotlin.container.ComponentProvider import org.jetbrains.kotlin.core.model.KotlinAnalysisFileCache import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.platform.TargetPlatform import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.diagnostics.KotlinSuppressCache import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode import org.jetbrains.kotlin.analyzer.ResolverForProject import org.jetbrains.kotlin.caches.resolve.PlatformAnalysisSettings import org.jetbrains.kotlin.diagnostics.DiagnosticSink import org.jetbrains.kotlin.idea.FrontendInternals class KotlinCacheServiceImpl(private val ideaProject: Project) : KotlinCacheService { override fun getResolutionFacadeWithForcedPlatform( elements: List, platform: TargetPlatform ): ResolutionFacade { return KotlinSimpleResolutionFacade(ideaProject, elements) } override fun getResolutionFacadeByFile(file: PsiFile, platform: TargetPlatform): ResolutionFacade { throw UnsupportedOperationException() } override fun getResolutionFacadeByModuleInfo( moduleInfo: ModuleInfo, settings: PlatformAnalysisSettings ): ResolutionFacade? { throw UnsupportedOperationException() } override fun getSuppressionCache(): KotlinSuppressCache { throw UnsupportedOperationException() } override fun getResolutionFacade(elements: List): ResolutionFacade { return KotlinSimpleResolutionFacade(ideaProject, elements) } override fun getResolutionFacade(element: KtElement): ResolutionFacade = getResolutionFacade(listOf(element)) override fun getResolutionFacadeByModuleInfo(moduleInfo: ModuleInfo, platform: TargetPlatform): ResolutionFacade? = null } @OptIn(FrontendInternals::class) class KotlinSimpleResolutionFacade( override val project: Project, private val elements: List) : ResolutionFacade { override fun tryGetFrontendService(element: PsiElement, serviceClass: Class): T? { return null } override fun resolveToDescriptor(declaration: KtDeclaration, bodyResolveMode: BodyResolveMode): DeclarationDescriptor { throw UnsupportedOperationException() } override val moduleDescriptor: ModuleDescriptor get() = throw UnsupportedOperationException() override fun analyze(element: KtElement, bodyResolveMode: BodyResolveMode): BindingContext { val ktFile = element.containingKtFile return KotlinAnalysisFileCache.getAnalysisResult(ktFile).analysisResult.bindingContext } override fun analyzeWithAllCompilerChecks( elements: Collection, callback: DiagnosticSink.DiagnosticsCallback? ): AnalysisResult { val ktFile = elements.first().containingKtFile return KotlinAnalysisFileCache.getAnalysisResult(ktFile).analysisResult } override fun analyze(elements: Collection, bodyResolveMode: BodyResolveMode): BindingContext { if (elements.isEmpty()) { return BindingContext.EMPTY } val ktFile = elements.first().containingKtFile return KotlinAnalysisFileCache.getAnalysisResult(ktFile).analysisResult.bindingContext } override fun getFrontendService(element: PsiElement, serviceClass: Class): T { throw UnsupportedOperationException() } override fun getFrontendService(serviceClass: Class): T { val files = elements.map { it.containingKtFile }.toSet() if (files.isEmpty()) throw IllegalStateException("Elements should not be empty") val componentProvider = KotlinAnalyzer.analyzeFiles(files).componentProvider ?: throw IllegalStateException("Trying to get service from non-initialized project") return componentProvider.getService(serviceClass) } override fun getFrontendService(moduleDescriptor: ModuleDescriptor, serviceClass: Class): T { throw UnsupportedOperationException() } override fun getIdeService(serviceClass: Class): T { throw UnsupportedOperationException() } override fun getResolverForProject(): ResolverForProject { throw UnsupportedOperationException() } } @Suppress("UNCHECKED_CAST") fun ComponentProvider.getService(request: Class): T { return resolve(request)!!.getValue() as T } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/KotlinPackagePartProvider.kt ================================================ /******************************************************************************* * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve import com.intellij.openapi.vfs.VirtualFile import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl import org.jetbrains.kotlin.core.log.KotlinLogger import org.jetbrains.kotlin.core.model.KotlinCommonEnvironment import org.jetbrains.kotlin.load.kotlin.PackagePartProvider import org.jetbrains.kotlin.metadata.jvm.deserialization.ModuleMapping import org.jetbrains.kotlin.metadata.jvm.deserialization.PackageParts import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration import org.jetbrains.kotlin.serialization.deserialization.ClassData import org.jetbrains.kotlin.utils.SmartList import java.io.EOFException import java.io.FileNotFoundException public class KotlinPackagePartProvider(private val environment: KotlinCommonEnvironment) : PackagePartProvider { private data class ModuleMappingInfo(val root: VirtualFile, val mapping: ModuleMapping, val name: String) private val notLoadedRoots by lazy(LazyThreadSafetyMode.NONE) { environment.getRoots() .map { it.file } .filter { it.findChild("META-INF") != null } .toMutableList() } private val loadedModules: MutableList = SmartList() private val deserializationConfiguration = CompilerDeserializationConfiguration(LanguageVersionSettingsImpl.DEFAULT) override fun getAnnotationsOnBinaryModule(moduleName: String): List = loadedModules.mapNotNull { (_, mapping, name) -> mapping.moduleData.annotations.takeIf { name == moduleName } } .flatten() .map { ClassId.fromString(it) } override fun findPackageParts(packageFqName: String): List { val rootToPackageParts = getPackageParts(packageFqName) if (rootToPackageParts.isEmpty()) return emptyList() val result = linkedSetOf() val visitedMultifileFacades = linkedSetOf() for ((_, packageParts) in rootToPackageParts) { for (name in packageParts.parts) { val facadeName = packageParts.getMultifileFacadeName(name) if (facadeName == null || facadeName !in visitedMultifileFacades) { result.add(name) } } packageParts.parts.mapNotNullTo(visitedMultifileFacades) { packageParts.getMultifileFacadeName(it) } } return result.toList() } override fun getAllOptionalAnnotationClasses(): List = emptyList() fun findMetadataPackageParts(packageFqName: String): List = getPackageParts(packageFqName).values.flatMap(PackageParts::metadataParts).distinct() @Synchronized private fun getPackageParts(packageFqName: String): Map { processNotLoadedRelevantRoots(packageFqName) val result = mutableMapOf() for ((root, mapping) in loadedModules) { val newParts = mapping.findPackageParts(packageFqName) ?: continue result[root]?.let { parts -> parts += newParts } ?: result.put(root, newParts) } return result } private fun processNotLoadedRelevantRoots(packageFqName: String) { if (notLoadedRoots.isEmpty()) return val pathParts = packageFqName.split('.') val relevantRoots = notLoadedRoots.filter { //filter all roots by package path existing pathParts.fold(it) { parent, part -> if (part.isEmpty()) parent else parent.findChild(part) ?: return@filter false } true } notLoadedRoots.removeAll(relevantRoots) for (root in relevantRoots) { val metaInf = root.findChild("META-INF") ?: continue val moduleFiles = metaInf.children.filter { it.name.endsWith(ModuleMapping.MAPPING_FILE_EXT) } for (moduleFile: VirtualFile in moduleFiles) { val mapping = try { ModuleMapping.loadModuleMapping( moduleFile.contentsToByteArray(), moduleFile.toString(), deserializationConfiguration.skipMetadataVersionCheck, deserializationConfiguration.isJvmPackageNameSupported ) { KotlinLogger.logWarning("Incompatible version for '$moduleFile': $it") } } catch (e: EOFException) { throw RuntimeException("Error on reading package parts for '$packageFqName' package in '$moduleFile', " + "roots: $notLoadedRoots", e) } catch (e: FileNotFoundException) { notLoadedRoots.add(root) continue } loadedModules.add(ModuleMappingInfo(root, mapping, moduleFile.nameWithoutExtension)) } } } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/KotlinResolutionFacade.kt ================================================ /******************************************************************************* * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve import com.intellij.openapi.project.Project import com.intellij.psi.PsiElement import org.eclipse.core.resources.IFile import org.jetbrains.kotlin.analyzer.AnalysisResult import org.jetbrains.kotlin.analyzer.ModuleInfo import org.jetbrains.kotlin.analyzer.ResolverForProject import org.jetbrains.kotlin.container.ComponentProvider import org.jetbrains.kotlin.container.getService import org.jetbrains.kotlin.core.model.getEnvironment import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.diagnostics.DiagnosticSink import org.jetbrains.kotlin.idea.FrontendInternals import org.jetbrains.kotlin.idea.resolve.ResolutionFacade import org.jetbrains.kotlin.psi.KtDeclaration import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode @OptIn(FrontendInternals::class) public class KotlinResolutionFacade( val eclipseFile: IFile, val componentProvider: ComponentProvider, override val moduleDescriptor: ModuleDescriptor) : ResolutionFacade { override fun tryGetFrontendService(element: PsiElement, serviceClass: Class): T? { throw UnsupportedOperationException() } override fun resolveToDescriptor(declaration: KtDeclaration, bodyResolveMode: BodyResolveMode): DeclarationDescriptor { throw UnsupportedOperationException() } override val project: Project get() = getEnvironment(eclipseFile).project override fun analyze(element: KtElement, bodyResolveMode: BodyResolveMode): BindingContext { throw UnsupportedOperationException() } override fun analyze(elements: Collection, bodyResolveMode: BodyResolveMode): BindingContext { throw UnsupportedOperationException() } override fun analyzeWithAllCompilerChecks( elements: Collection, callback: DiagnosticSink.DiagnosticsCallback? ): AnalysisResult { throw UnsupportedOperationException() } override fun getFrontendService(element: PsiElement, serviceClass: Class): T { throw UnsupportedOperationException() } override fun getFrontendService(serviceClass: Class): T = componentProvider.getService(serviceClass) override fun getFrontendService(moduleDescriptor: ModuleDescriptor, serviceClass: Class): T { throw UnsupportedOperationException() } override fun getIdeService(serviceClass: Class): T { throw UnsupportedOperationException() } override fun getResolverForProject(): ResolverForProject { throw UnsupportedOperationException() } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/KotlinSourceIndex.java ================================================ package org.jetbrains.kotlin.core.resolve; import java.io.File; import java.util.Map; import java.util.WeakHashMap; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.internal.core.PackageFragment; import org.eclipse.jdt.internal.core.SourceMapper; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.core.log.KotlinLogger; import org.jetbrains.kotlin.core.model.KotlinEnvironment; import org.jetbrains.kotlin.core.resolve.sources.LibrarySourcesIndex; import org.jetbrains.kotlin.core.resolve.sources.LibrarySourcesIndexKt; import org.jetbrains.kotlin.idea.KotlinFileType; import com.intellij.openapi.components.ServiceManager; import com.intellij.openapi.project.Project; public class KotlinSourceIndex { private final Map packageIndexes = new WeakHashMap< >(); public static KotlinSourceIndex getInstance(IJavaProject javaProject) { Project ideaProject = KotlinEnvironment.Companion.getEnvironment(javaProject.getProject()).getProject(); return ServiceManager.getService(ideaProject, KotlinSourceIndex.class); } public static boolean isKotlinSource(String shortFileName) { return KotlinFileType.EXTENSION.equals(new Path(shortFileName).getFileExtension()); } @Nullable public static char[] getSource(SourceMapper mapper, IType type, String simpleSourceFileName) { IPackageFragment packageFragment = type.getPackageFragment(); if (packageFragment instanceof PackageFragment) { KotlinSourceIndex index = KotlinSourceIndex.getInstance(type.getJavaProject()); String resolvedPath = index.resolvePath((PackageFragment) packageFragment, simpleSourceFileName); return mapper.findSource(resolvedPath); } return null; } @Nullable public static char[] getSource(SourceMapper mapper, String sourceFileName, IPath packageFolder, IPath sourcePath) { LibrarySourcesIndex index = createSourcesIndex(sourcePath); String result = index != null ? index.resolve(sourceFileName, packageFolder) : null; return result != null ? mapper.findSource(result) : mapper.findSource(packageFolder.append(sourceFileName).toPortableString()); } public String resolvePath(PackageFragment packageFragment, String pathToSource) { IPackageFragmentRoot packageFragmentRoot = packageFragment.getPackageFragmentRoot(); LibrarySourcesIndex packageIndex = getIndexForRoot(packageFragmentRoot); if (packageIndex == null) { return pathToSource; } String simpleName = new Path(pathToSource).lastSegment(); String result = packageIndex.resolve(simpleName, packageFragment.getElementName()); return result != null ? result : pathToSource; } @Nullable private LibrarySourcesIndex getIndexForRoot(IPackageFragmentRoot packageRoot) { LibrarySourcesIndex result = packageIndexes.get(packageRoot); if (result != null) { return result; } try { if (packageRoot.getKind() != IPackageFragmentRoot.K_BINARY) { return null; } IPath sourcePath = LibrarySourcesIndexKt.getSourcePath(packageRoot); if (sourcePath == null) { return null; } LibrarySourcesIndex index = createSourcesIndex(sourcePath); packageIndexes.put(packageRoot, index); return index; } catch (JavaModelException e) { KotlinLogger.logError("Unable to analyze sources for package", e); } return null; } @Nullable private static LibrarySourcesIndex createSourcesIndex(IPath sourcePath) { File jarFile = sourcePath.toFile(); return jarFile.exists() ? new LibrarySourcesIndex(jarFile) : null; } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/injection.kt ================================================ /******************************************************************************* * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve import com.intellij.openapi.project.Project import com.intellij.psi.search.GlobalSearchScope import org.eclipse.jdt.core.IJavaProject import org.jetbrains.kotlin.builtins.jvm.JvmBuiltIns import org.jetbrains.kotlin.builtins.jvm.JvmBuiltInsPackageFragmentProvider import org.jetbrains.kotlin.config.JvmAnalysisFlags import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.container.ComponentProvider import org.jetbrains.kotlin.container.StorageComponentContainer import org.jetbrains.kotlin.container.registerSingleton import org.jetbrains.kotlin.container.useInstance import org.jetbrains.kotlin.context.ModuleContext import org.jetbrains.kotlin.core.resolve.lang.java.EclipseJavaClassFinder import org.jetbrains.kotlin.core.resolve.lang.java.resolver.EclipseJavaSourceElementFactory import org.jetbrains.kotlin.core.resolve.lang.java.resolver.EclipseTraceBasedJavaResolverCache import org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaPropertyInitializerEvaluator import org.jetbrains.kotlin.frontend.di.configureModule import org.jetbrains.kotlin.incremental.InlineConstTrackerImpl import org.jetbrains.kotlin.incremental.components.LookupTracker import org.jetbrains.kotlin.load.java.InternalFlexibleTypeTransformer import org.jetbrains.kotlin.load.java.JavaClassesTracker import org.jetbrains.kotlin.load.java.JavaModuleAnnotationsProvider import org.jetbrains.kotlin.load.java.components.SignaturePropagatorImpl import org.jetbrains.kotlin.load.java.components.TraceBasedErrorReporter import org.jetbrains.kotlin.load.java.lazy.JavaResolverSettings import org.jetbrains.kotlin.load.java.lazy.ModuleClassResolver import org.jetbrains.kotlin.load.kotlin.DeserializationComponentsForJava import org.jetbrains.kotlin.load.kotlin.PackagePartProvider import org.jetbrains.kotlin.load.kotlin.VirtualFileFinderFactory import org.jetbrains.kotlin.platform.jvm.JvmPlatforms import org.jetbrains.kotlin.resolve.* import org.jetbrains.kotlin.resolve.jvm.JavaDescriptorResolver import org.jetbrains.kotlin.resolve.jvm.SyntheticJavaPartsProvider import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices import org.jetbrains.kotlin.resolve.lazy.ResolveSession import org.jetbrains.kotlin.resolve.lazy.declarations.DeclarationProviderFactory fun StorageComponentContainer.configureJavaTopDownAnalysis( moduleContentScope: GlobalSearchScope, project: Project, lookupTracker: LookupTracker, languageFeatureSettings: LanguageVersionSettings) { useInstance(moduleContentScope) useInstance(lookupTracker) useImpl() useImpl() useImpl() useImpl() useInstance(VirtualFileFinderFactory.SERVICE.getInstance(project).create(moduleContentScope)) useImpl() useImpl() useImpl() useImpl() useInstance(InternalFlexibleTypeTransformer) } fun createContainerForLazyResolveWithJava( moduleContext: ModuleContext, bindingTrace: BindingTrace, declarationProviderFactory: DeclarationProviderFactory, moduleContentScope: GlobalSearchScope, moduleClassResolver: ModuleClassResolver, targetEnvironment: TargetEnvironment, lookupTracker: LookupTracker, packagePartProvider: PackagePartProvider, jvmTarget: JvmTarget, languageVersionSettings: LanguageVersionSettings, javaProject: IJavaProject?, useBuiltInsProvider: Boolean, javaModuleAnnotationsProvider: JavaModuleAnnotationsProvider, analyzerService: PlatformDependentAnalyzerServices? ): StorageComponentContainer = createContainer("LazyResolveWithJava", JvmPlatformAnalyzerServices) { configureModule( moduleContext, JvmPlatforms.jvmPlatformByTargetVersion(jvmTarget), analyzerService ?: JvmPlatformAnalyzerServices, bindingTrace, languageVersionSettings ) configureJavaTopDownAnalysis(moduleContentScope, moduleContext.project, lookupTracker, languageVersionSettings) useImpl() useImpl() useImpl() useImpl() useInstance(SyntheticJavaPartsProvider.EMPTY) useInstance(packagePartProvider) useInstance(moduleClassResolver) useInstance(javaModuleAnnotationsProvider) useInstance(declarationProviderFactory) javaProject?.let { useInstance(it) } //TODO??? useInstance(languageVersionSettings.getFlag(JvmAnalysisFlags.javaTypeEnhancementState)) if (useBuiltInsProvider) { //TODO??? useInstance((moduleContext.module.builtIns as JvmBuiltIns).customizer) useImpl() } useInstance(JavaClassesTracker.Default) targetEnvironment.configure(this) useInstance( JavaResolverSettings.create( //isReleaseCoroutines = languageVersionSettings.supportsFeature(LanguageFeature.ReleaseCoroutines), correctNullabilityForNotNullTypeParameter = false, typeEnhancementImprovementsInStrictMode = false, ignoreNullabilityForErasedValueParameters = false ) ) }.apply { get().initialize(bindingTrace, get(),languageVersionSettings, jvmTarget) } fun createContainerForTopDownAnalyzerForJvm( moduleContext: ModuleContext, bindingTrace: BindingTrace, declarationProviderFactory: DeclarationProviderFactory, moduleContentScope: GlobalSearchScope, lookupTracker: LookupTracker, packagePartProvider: PackagePartProvider, jvmTarget: JvmTarget, languageVersionSettings: LanguageVersionSettings, moduleClassResolver: ModuleClassResolver, javaProject: IJavaProject?, javaModuleAnnotationsProvider: JavaModuleAnnotationsProvider, analyzerService: PlatformDependentAnalyzerServices? ): ComponentProvider = createContainerForLazyResolveWithJava( moduleContext, bindingTrace, declarationProviderFactory, moduleContentScope, moduleClassResolver, CompilerEnvironment, lookupTracker, packagePartProvider, jvmTarget, languageVersionSettings, javaProject, useBuiltInsProvider = true, javaModuleAnnotationsProvider, analyzerService ) // Copy functions from Dsl.kt as they were shrinked by proguard inline fun StorageComponentContainer.useImpl() { registerSingleton(T::class.java) } inline fun ComponentProvider.get(): T { return getService(T::class.java) } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/EclipseJavaClassFinder.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.java; import com.intellij.mock.MockProject; import org.eclipse.core.resources.IFolder; import org.eclipse.jdt.core.*; import org.eclipse.jdt.core.dom.*; import org.eclipse.jdt.internal.core.JavaProject; import org.eclipse.jdt.internal.core.NameLookup; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.config.JvmTarget; import org.jetbrains.kotlin.config.LanguageVersionSettings; import org.jetbrains.kotlin.core.log.KotlinLogger; import org.jetbrains.kotlin.core.model.KotlinEnvironment; import org.jetbrains.kotlin.core.model.KotlinJavaManager; import org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaClass; import org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaPackage; import org.jetbrains.kotlin.load.java.AbstractJavaClassFinder; import org.jetbrains.kotlin.load.java.structure.JavaClass; import org.jetbrains.kotlin.load.java.structure.JavaPackage; import org.jetbrains.kotlin.name.ClassId; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.resolve.BindingTrace; import org.jetbrains.kotlin.resolve.CodeAnalyzerInitializer; import org.jetbrains.kotlin.resolve.jvm.JvmCodeAnalyzerInitializer; import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer; import java.util.Arrays; import java.util.Set; public class EclipseJavaClassFinder extends AbstractJavaClassFinder { private IJavaProject javaProject; public EclipseJavaClassFinder(@NotNull IJavaProject project) { javaProject = project; } @Override public void initialize(@NotNull BindingTrace trace, @NotNull KotlinCodeAnalyzer codeAnalyzer, @NotNull LanguageVersionSettings languageVersionSettings, @NotNull JvmTarget jvmTarget) { if (javaProject == null) { return; } MockProject ideaProject = KotlinEnvironment.Companion.getEnvironment(javaProject.getProject()).getProject(); JvmCodeAnalyzerInitializer tempInitializer = (JvmCodeAnalyzerInitializer) CodeAnalyzerInitializer.Companion.getInstance(ideaProject); //trace, codeAnalyzer.getModuleDescriptor(), codeAnalyzer, languageVersionSettings tempInitializer.initialize(trace, codeAnalyzer.getModuleDescriptor(), codeAnalyzer, languageVersionSettings, jvmTarget); //trace, codeAnalyzer.getModuleDescriptor(), codeAnalyzer } @Nullable @Override public JavaPackage findPackage(@NotNull FqName fqName, boolean b) { IPackageFragment[] packageFragments = findPackageFragments(javaProject, fqName.asString(), false, false); if (packageFragments != null && packageFragments.length > 0) { return new EclipseJavaPackage(Arrays.asList(packageFragments)); } return null; } @Override @Nullable public JavaClass findClass(@NotNull Request request) { return findClass(request.getClassId()); } @Override @Nullable public JavaClass findClass(@NotNull ClassId classId) { ITypeBinding typeBinding = findType(classId.asSingleFqName(), javaProject); if (typeBinding != null) { return new EclipseJavaClass(typeBinding); } return null; } @Nullable public static IPackageFragment[] findPackageFragments(IJavaProject javaProject, String name, boolean partialMatch, boolean patternMatch) { try { NameLookup nameLookup = ((JavaProject) javaProject).newNameLookup((WorkingCopyOwner) null); return nameLookup.findPackageFragments(name, partialMatch, patternMatch); } catch (JavaModelException e) { KotlinLogger.logAndThrow(e); } return null; } @Nullable public static ITypeBinding findType(@NotNull FqName fqName, @NotNull IJavaProject javaProject) { IType eclipseType = null; try { eclipseType = javaProject.findType(fqName.asString()); } catch (JavaModelException e) { KotlinLogger.logAndThrow(e); } if (eclipseType != null) { return !isInKotlinBinFolder(eclipseType) ? createTypeBinding(eclipseType) : null; } return null; } public static boolean isInKotlinBinFolder(@NotNull IType eclipseType) { IFolder kotlinBinFolder = KotlinJavaManager.INSTANCE.getKotlinBinFolderFor(eclipseType.getJavaProject().getProject()); IPackageFragmentRoot packageFragmentRoot = (IPackageFragmentRoot) eclipseType.getPackageFragment().getParent(); return kotlinBinFolder.equals(packageFragmentRoot.getResource()); } public static ITypeBinding createTypeBinding(IType type) { ASTParser parser = ASTParser.newParser(AST.JLS8); parser.setCompilerOptions(type.getJavaProject().getOptions(true)); parser.setIgnoreMethodBodies(true); if (type.getCompilationUnit() != null) { parser.setSource(type.getCompilationUnit()); } else { // class file with no source parser.setProject(type.getJavaProject()); IBinding[] bindings = parser.createBindings(new IJavaElement[] { type }, null); if (bindings.length == 1 && bindings[0] instanceof ITypeBinding) { return (ITypeBinding) bindings[0]; } return null; } parser.setResolveBindings(true); CompilationUnit root = (CompilationUnit) parser.createAST(null); return getTypeBinding(root, type); } private static ASTNode getParent(ASTNode node, Class parentClass) { do { node = node.getParent(); } while (node != null && !parentClass.isInstance(node)); return node; } private static ITypeBinding getTypeBinding(CompilationUnit root, IType type) { try { if (type.isAnonymous()) { final IJavaElement parent = type.getParent(); if (parent instanceof IField && Flags.isEnum(((IMember) parent).getFlags())) { final EnumConstantDeclaration constant = (EnumConstantDeclaration) NodeFinder.perform(root, ((ISourceReference) parent).getSourceRange()); if (constant != null) { final AnonymousClassDeclaration declaration = constant.getAnonymousClassDeclaration(); if (declaration != null) return declaration.resolveBinding(); } } else { final ClassInstanceCreation creation = (ClassInstanceCreation) getParent( NodeFinder.perform(root, type.getNameRange()), ClassInstanceCreation.class); if (creation != null) return creation.resolveTypeBinding(); } } else { final AbstractTypeDeclaration declaration = (AbstractTypeDeclaration) getParent(NodeFinder.perform(root, type.getNameRange()), AbstractTypeDeclaration.class); if (declaration != null) return declaration.resolveBinding(); } } catch (JavaModelException e) { KotlinLogger.logAndThrow(e); } return null; } @Override @Nullable public Set knownClassNamesInPackage(@NotNull FqName packageFqName) { // TODO Auto-generated method stub return null; } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/resolver/EclipseJavaSourceElement.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.java.resolver; import org.eclipse.jdt.core.dom.IBinding; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaElement; import org.jetbrains.kotlin.descriptors.SourceFile; import org.jetbrains.kotlin.load.java.sources.JavaSourceElement; import org.jetbrains.kotlin.load.java.structure.JavaElement; public class EclipseJavaSourceElement implements JavaSourceElement { private final JavaElement javaElement; public EclipseJavaSourceElement(JavaElement javaElement) { this.javaElement = javaElement; } @Override @NotNull public JavaElement getJavaElement() { return javaElement; } @NotNull public IBinding getElementBinding() { return ((EclipseJavaElement) javaElement).getBinding(); } @Override @NotNull public SourceFile getContainingFile() { return SourceFile.NO_SOURCE_FILE; } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/resolver/EclipseJavaSourceElementFactory.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.java.resolver; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.load.java.sources.JavaSourceElement; import org.jetbrains.kotlin.load.java.sources.JavaSourceElementFactory; import org.jetbrains.kotlin.load.java.structure.JavaElement; public class EclipseJavaSourceElementFactory implements JavaSourceElementFactory { @Override @NotNull public JavaSourceElement source(@NotNull JavaElement javaElement) { return new EclipseJavaSourceElement(javaElement); } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/resolver/EclipseTraceBasedJavaResolverCache.kt ================================================ /******************************************************************************* * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.java.resolver import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ConstructorDescriptor import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.load.java.components.JavaResolverCache import org.jetbrains.kotlin.load.java.structure.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.tail import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingTrace import org.jetbrains.kotlin.resolve.lazy.ResolveSession import org.jetbrains.kotlin.resolve.lazy.ResolveSessionUtils import javax.inject.Inject class EclipseTraceBasedJavaResolverCache(@Inject val trace: BindingTrace, @Inject val resolveSession: ResolveSession) : JavaResolverCache { override fun getClassResolvedFromSource(fqName: FqName): ClassDescriptor? { return trace[BindingContext.FQNAME_TO_CLASS_DESCRIPTOR, fqName.toUnsafe()] ?: findInPackageFragments(fqName) } override fun recordMethod(p0: JavaMember, p1: SimpleFunctionDescriptor) { } override fun recordConstructor(element: JavaElement, descriptor: ConstructorDescriptor) { } override fun recordField(field: JavaField, descriptor: PropertyDescriptor) { } override fun recordClass(javaClass: JavaClass, descriptor: ClassDescriptor) { } // Copied from org.jetbrains.kotlin.load.java.components.LazyResolveBasedCache private fun findInPackageFragments(fullFqName: FqName): ClassDescriptor? { var fqName = if (fullFqName.isRoot) fullFqName else fullFqName.parent() while (true) { val packageDescriptor = resolveSession.getPackageFragment(fqName) if (packageDescriptor == null) break val result = ResolveSessionUtils.findClassByRelativePath( packageDescriptor.getMemberScope(), fullFqName.tail(fqName)) if (result != null) return result if (fqName.isRoot) break fqName = fqName.parent() } return null } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaAnnotation.kt ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.jetbrains.kotlin.core.resolve.lang.java.structure import org.eclipse.jdt.core.IJavaProject import org.eclipse.jdt.core.dom.IAnnotationBinding import org.jetbrains.kotlin.load.java.structure.JavaAnnotation import org.jetbrains.kotlin.load.java.structure.JavaAnnotationArgument import org.jetbrains.kotlin.load.java.structure.JavaClass import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name import java.util.* class EclipseJavaAnnotation(javaAnnotation: IAnnotationBinding) : EclipseJavaElement(javaAnnotation), JavaAnnotation { private val javaProject: IJavaProject = javaAnnotation.annotationType.getPackage().javaElement.javaProject override val arguments: Collection get() { val arguments = ArrayList() for (memberValuePair in binding.declaredMemberValuePairs) { arguments.add( EclipseJavaAnnotationArgument.create( memberValuePair.value, Name.identifier(memberValuePair.name), javaProject ) ) } return arguments } override val classId: ClassId? get() { val annotationType = binding.annotationType return if (annotationType != null) EclipseJavaElementUtil.computeClassId(annotationType) else null } override fun resolve(): JavaClass? { val annotationType = binding.annotationType return if (annotationType != null) EclipseJavaClass(annotationType) else null } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaAnnotationArgument.kt ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.java.structure import org.eclipse.jdt.core.IJavaProject import org.eclipse.jdt.core.dom.IAnnotationBinding import org.eclipse.jdt.core.dom.IBinding import org.eclipse.jdt.core.dom.ITypeBinding import org.eclipse.jdt.core.dom.IVariableBinding import org.jetbrains.kotlin.load.java.structure.JavaAnnotationArgument import org.jetbrains.kotlin.name.Name public abstract class EclipseJavaAnnotationArgument(javaElement: T) : EclipseJavaElement(javaElement), JavaAnnotationArgument { override val name: Name? get() = Name.identifier(binding.getName()) companion object { @JvmStatic fun create(value: Any, name: Name, javaProject: IJavaProject): JavaAnnotationArgument { return when (value) { is IAnnotationBinding -> EclipseJavaAnnotationAsAnnotationArgument(value, name) is IVariableBinding -> EclipseJavaReferenceAnnotationArgument(value) is Array<*> -> EclipseJavaArrayAnnotationArgument(value, name, javaProject) is Class<*> -> EclipseJavaClassObjectAnnotationArgument(value, name, javaProject) is ITypeBinding -> EclipseJavaTypeAsAnnotationArgument(value, name) is String, is Boolean, is Int, is Short, is Long, is Byte, is Float, is Double, is Char -> EclipseJavaLiteralAnnotationArgument(value, name) else -> throw IllegalArgumentException("Wrong annotation argument: $value") } } } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaAnnotationAsAnnotationArgument.kt ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.java.structure import org.eclipse.jdt.core.dom.IAnnotationBinding import org.jetbrains.kotlin.load.java.structure.JavaAnnotation import org.jetbrains.kotlin.load.java.structure.JavaAnnotationAsAnnotationArgument import org.jetbrains.kotlin.name.Name public class EclipseJavaAnnotationAsAnnotationArgument( private val annotation: IAnnotationBinding, override val name: Name?) : JavaAnnotationAsAnnotationArgument { override public fun getAnnotation(): JavaAnnotation = EclipseJavaAnnotation(annotation) } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaArrayAnnotationArgument.kt ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.java.structure import org.eclipse.jdt.core.IJavaProject import org.jetbrains.kotlin.load.java.structure.JavaAnnotationArgument import org.jetbrains.kotlin.load.java.structure.JavaArrayAnnotationArgument import org.jetbrains.kotlin.name.Name public class EclipseJavaArrayAnnotationArgument( private val arguments: Array<*>, override val name: Name, private val javaProject: IJavaProject) : JavaArrayAnnotationArgument { override public fun getElements(): List { return arguments.map { EclipseJavaAnnotationArgument.create(it!!, name, javaProject) } } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaArrayType.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.java.structure; import org.eclipse.jdt.core.dom.ITypeBinding; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.load.java.structure.JavaArrayType; import org.jetbrains.kotlin.load.java.structure.JavaType; public class EclipseJavaArrayType extends EclipseJavaType implements JavaArrayType { public EclipseJavaArrayType(@NotNull ITypeBinding typeBinding) { super(typeBinding); } @Override @NotNull public JavaType getComponentType() { return EclipseJavaType.create(getBinding().getComponentType()); } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaClass.kt ================================================ /******************************************************************************* * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.java.structure import org.eclipse.jdt.core.dom.ITypeBinding import org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaElementFactory.classifierTypes import org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaElementFactory.typeParameters import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.load.java.structure.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.SpecialNames import java.lang.reflect.Modifier public class EclipseJavaClass(javaElement: ITypeBinding) : EclipseJavaClassifier(javaElement), JavaClass { override val name: Name = SpecialNames.safeIdentifier(binding.getName()) override val isAbstract: Boolean = Modifier.isAbstract(binding.getModifiers()) override val isStatic: Boolean = Modifier.isStatic(binding.getModifiers()) override val isFinal: Boolean = Modifier.isFinal(binding.getModifiers()) override val visibility: Visibility = EclipseJavaElementUtil.getVisibility(binding) override val typeParameters: List get() = typeParameters(binding.getTypeParameters()) override val innerClassNames: Collection get() = binding.declaredTypes.mapNotNull { it.name?.takeIf(Name::isValidIdentifier)?.let(Name::identifier) } override fun findInnerClass(name: Name): JavaClass? { return binding.declaredTypes.find { it.name == name.asString() }?.let(::EclipseJavaClass) } override val fqName: FqName? = binding.getQualifiedName()?.let { FqName(it) } override val isInterface: Boolean = binding.isInterface() override val isRecord: Boolean get() = false //TODO override val isSealed: Boolean get() = false //TODO override val isAnnotationType: Boolean = binding.isAnnotation() override val isEnum: Boolean = binding.isEnum() override val outerClass: JavaClass? get() = binding.getDeclaringClass()?.let { EclipseJavaClass(it) } override val permittedTypes: Collection get() = emptyList() //TODO override val recordComponents: Collection get() = emptyList() // TODO override val supertypes: Collection get() = classifierTypes(EclipseJavaElementUtil.getSuperTypesWithObject(binding)) override val methods: Collection get() = binding.declaredMethods.filterNot { it.isConstructor() }.map(::EclipseJavaMethod) override val fields: Collection get() = binding.getDeclaredFields() .filter { val name = it.getName() name != null && Name.isValidIdentifier(name) } .map { EclipseJavaField(it) } override val constructors: Collection get() = binding.declaredMethods.filter { it.isConstructor() }.map(::EclipseJavaConstructor) override val isDeprecatedInJavaDoc: Boolean = binding.isDeprecated override val annotations: Collection get() = binding.annotations.map(::EclipseJavaAnnotation) override val lightClassOriginKind: LightClassOriginKind? get() = binding.javaElement.let { if (EclipseJavaElementUtil.isKotlinLightClass(it)) LightClassOriginKind.SOURCE else null } override fun hasDefaultConstructor() = !isInterface && constructors.isEmpty() } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaClassObjectAnnotationArgument.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.java.structure; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.dom.ITypeBinding; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.load.java.structure.JavaClassObjectAnnotationArgument; import org.jetbrains.kotlin.load.java.structure.JavaType; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.core.resolve.lang.java.EclipseJavaClassFinder; public class EclipseJavaClassObjectAnnotationArgument implements JavaClassObjectAnnotationArgument { private final Class javaClass; private final IJavaProject javaProject; private final Name name; protected EclipseJavaClassObjectAnnotationArgument(Class javaClass, @NotNull Name name, @NotNull IJavaProject javaProject) { this.javaClass = javaClass; this.name = name; this.javaProject = javaProject; } @Override @NotNull public JavaType getReferencedType() { ITypeBinding typeBinding = EclipseJavaClassFinder.findType(new FqName(javaClass.getCanonicalName()), javaProject); assert typeBinding != null; return EclipseJavaType.create(typeBinding); } @Override @Nullable public Name getName() { return name; } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaClassifier.kt ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.java.structure import org.eclipse.jdt.core.dom.ITypeBinding import org.jetbrains.kotlin.load.java.structure.JavaClassifier import org.jetbrains.kotlin.load.java.structure.JavaAnnotationOwner import org.jetbrains.kotlin.load.java.structure.JavaAnnotation import org.jetbrains.kotlin.name.FqName public abstract class EclipseJavaClassifier(javaType: T) : EclipseJavaElement(javaType), JavaClassifier, JavaAnnotationOwner { companion object { @JvmStatic fun create(element: ITypeBinding): JavaClassifier { return when { element.isTypeVariable() -> EclipseJavaTypeParameter(element) element.isClass() || element.isParameterizedType() || element.isInterface() || element.isEnum() -> EclipseJavaClass(element) else -> throw IllegalArgumentException("Element: ${element.getName()} is not JavaClassifier") } } } override val annotations: Collection get() = binding.getAnnotations().map(::EclipseJavaAnnotation) override fun findAnnotation(fqName: FqName): JavaAnnotation? { return EclipseJavaElementUtil.findAnnotation(binding.getAnnotations(), fqName) } override val isDeprecatedInJavaDoc: Boolean = binding.isDeprecated() } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaClassifierType.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.java.structure; import static org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaElementFactory.types; import java.util.List; import org.eclipse.jdt.core.dom.ITypeBinding; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.load.java.structure.JavaClassifier; import org.jetbrains.kotlin.load.java.structure.JavaClassifierType; import org.jetbrains.kotlin.load.java.structure.JavaType; public class EclipseJavaClassifierType extends EclipseJavaType implements JavaClassifierType { public EclipseJavaClassifierType(ITypeBinding typeBinding) { super(typeBinding); } @Override @Nullable public JavaClassifier getClassifier() { return EclipseJavaClassifier.Companion.create(getBinding().getTypeDeclaration()); } @Override @NotNull public String getPresentableText() { return getBinding().getQualifiedName(); } @Override public boolean isRaw() { return getBinding().isRawType(); } @Override @NotNull public List getTypeArguments() { return types(getBinding().getTypeArguments()); } @Override @NotNull public String getClassifierQualifiedName() { return getBinding().getName(); } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaConstructor.java ================================================ package org.jetbrains.kotlin.core.resolve.lang.java.structure; import static org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaElementFactory.typeParameters; import java.util.List; import org.eclipse.jdt.core.dom.IMethodBinding; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.load.java.structure.JavaClass; import org.jetbrains.kotlin.load.java.structure.JavaConstructor; import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter; import org.jetbrains.kotlin.load.java.structure.JavaValueParameter; public class EclipseJavaConstructor extends EclipseJavaMember implements JavaConstructor { public EclipseJavaConstructor(@NotNull IMethodBinding methodBinding) { super(methodBinding); assert methodBinding.isConstructor() : "Method binding which is not a constructor should not be wrapped in EclipseJavaConstructor: " + methodBinding.getName(); } @Override @NotNull public JavaClass getContainingClass() { return new EclipseJavaClass(getBinding().getDeclaringClass()); } @Override @NotNull public List getTypeParameters() { return typeParameters(getBinding().getTypeParameters()); } @Override @NotNull public List getValueParameters() { return EclipseJavaElementUtil.getValueParameters(getBinding()); } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaElement.kt ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.java.structure import org.eclipse.jdt.core.dom.IBinding import org.jetbrains.kotlin.load.java.structure.JavaElement abstract class EclipseJavaElement protected constructor(val binding: T) : JavaElement { override fun hashCode(): Int = binding.hashCode() override fun equals(other: Any?): Boolean = other is EclipseJavaElement<*> && binding == other.binding } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaElementFactory.java ================================================ /******************************************************************************* * Copyright 2010-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.java.structure; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.eclipse.jdt.core.dom.IAnnotationBinding; import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.core.dom.IVariableBinding; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.load.java.structure.JavaAnnotation; import org.jetbrains.kotlin.load.java.structure.JavaClassifierType; import org.jetbrains.kotlin.load.java.structure.JavaField; import org.jetbrains.kotlin.load.java.structure.JavaMethod; import org.jetbrains.kotlin.load.java.structure.JavaType; import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter; public class EclipseJavaElementFactory { private EclipseJavaElementFactory() { } private interface Factory { @NotNull Java create(@NotNull Binding binding); } private static class Factories { private static final Factory ANNOTATIONS = new Factory() { @Override @NotNull public JavaAnnotation create(@NotNull IAnnotationBinding annotationBinding) { return new EclipseJavaAnnotation(annotationBinding); } }; private static final Factory CLASSIFIER_TYPES = new Factory() { @Override @NotNull public JavaClassifierType create(@NotNull ITypeBinding typeBinding) { return new EclipseJavaClassifierType(typeBinding); } }; private static final Factory TYPES = new Factory() { @Override @NotNull public JavaType create(@NotNull ITypeBinding typeBinding) { return EclipseJavaType.create(typeBinding); } }; private static final Factory METHODS = new Factory() { @Override @NotNull public JavaMethod create(@NotNull IMethodBinding methodBinding) { return new EclipseJavaMethod(methodBinding); } }; private static final Factory FIELDS = new Factory() { @Override @NotNull public JavaField create(@NotNull IVariableBinding variableBinding) { return new EclipseJavaField(variableBinding); } }; private static final Factory TYPE_PARAMETERS = new Factory() { @Override @NotNull public JavaTypeParameter create(@NotNull ITypeBinding typeParameterBinding) { return new EclipseJavaTypeParameter(typeParameterBinding); } }; } @NotNull private static List convert(@NotNull Binding[] elements, @NotNull Factory factory) { if (elements.length == 0) return Collections.emptyList(); List result = new ArrayList(); for (Binding element : elements) { result.add(factory.create(element)); } return result; } @NotNull public static List annotations(@NotNull IAnnotationBinding[] annotations) { return convert(annotations, Factories.ANNOTATIONS); } @NotNull public static List classifierTypes(@NotNull ITypeBinding[] classTypes) { return convert(classTypes, Factories.CLASSIFIER_TYPES); } @NotNull public static List methods(@NotNull IMethodBinding[] methods) { return convert(methods, Factories.METHODS); } @NotNull public static List fields(@NotNull IVariableBinding[] variables) { return convert(variables, Factories.FIELDS); } @NotNull public static List types(@NotNull ITypeBinding[] types) { return convert(types, Factories.TYPES); } @NotNull public static List typeParameters(@NotNull ITypeBinding[] typeParameters) { return convert(typeParameters, Factories.TYPE_PARAMETERS); } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaElementUtil.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.java.structure; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.jdt.core.IClassFile; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.dom.IAnnotationBinding; import org.eclipse.jdt.core.dom.IBinding; import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.ITypeBinding; import org.eclipse.jdt.internal.compiler.env.IBinaryAnnotation; import org.eclipse.jdt.internal.core.BinaryMethod; import org.eclipse.jdt.internal.core.BinaryType; import org.eclipse.jdt.internal.core.ClassFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.core.filesystem.KotlinFileSystem; import org.jetbrains.kotlin.core.log.KotlinLogger; import org.jetbrains.kotlin.core.resolve.lang.java.EclipseJavaClassFinder; import org.jetbrains.kotlin.core.utils.ProjectUtils; import org.jetbrains.kotlin.descriptors.Visibilities; import org.jetbrains.kotlin.descriptors.Visibility; import org.jetbrains.kotlin.descriptors.java.JavaVisibilities; import org.jetbrains.kotlin.load.java.structure.JavaAnnotation; import org.jetbrains.kotlin.load.java.structure.JavaValueParameter; import org.jetbrains.kotlin.load.kotlin.KotlinBinaryClassCache; import org.jetbrains.kotlin.load.kotlin.KotlinClassFinder; import org.jetbrains.kotlin.name.ClassId; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.Name; import org.eclipse.jdt.core.dom.Modifier; import org.eclipse.jdt.core.Flags; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.psi.CommonClassNames; public class EclipseJavaElementUtil { @NotNull static Visibility getVisibility(@NotNull IBinding member) { int flags = member.getModifiers(); if (Modifier.isPublic(flags)) { return Visibilities.Public.INSTANCE; } else if (Modifier.isPrivate(flags)) { return Visibilities.Private.INSTANCE; } else if (Modifier.isProtected(flags)) { return Flags.isStatic(flags) ? JavaVisibilities.ProtectedAndPackage.INSTANCE : JavaVisibilities.ProtectedAndPackage.INSTANCE; } return JavaVisibilities.PackageVisibility.INSTANCE; } private static List getSuperTypes(@NotNull ITypeBinding typeBinding) { List superTypes = new ArrayList<>(); for (ITypeBinding superInterface : typeBinding.getInterfaces()) { superTypes.add(superInterface); } ITypeBinding superClass = typeBinding.getSuperclass(); if (superClass != null) { superTypes.add(superClass); } return superTypes; } static ITypeBinding[] getSuperTypesWithObject(@NotNull ITypeBinding typeBinding) { List allSuperTypes = new ArrayList<>(); boolean javaLangObjectInSuperTypes = false; for (ITypeBinding superType : getSuperTypes(typeBinding)) { if (superType.getQualifiedName().equals(CommonClassNames.JAVA_LANG_OBJECT)) { javaLangObjectInSuperTypes = true; } allSuperTypes.add(superType); } if (!javaLangObjectInSuperTypes && !typeBinding.getQualifiedName().equals(CommonClassNames.JAVA_LANG_OBJECT)) { allSuperTypes.add(getJavaLangObjectBinding(typeBinding.getJavaElement().getJavaProject())); } return allSuperTypes.toArray(new ITypeBinding[allSuperTypes.size()]); } @NotNull private static ITypeBinding getJavaLangObjectBinding(@NotNull IJavaProject javaProject) { try { IType javaType = javaProject.findType(CommonClassNames.JAVA_LANG_OBJECT); if(javaType == null) { return null; // this happens if the project was modified while analyzing in progress. } return EclipseJavaClassFinder.createTypeBinding(javaType); } catch (JavaModelException e) { KotlinLogger.logAndThrow(e); throw new IllegalStateException(e); } } @NotNull static List getValueParameters(@NotNull IMethodBinding method) { List parameters = new ArrayList(); ITypeBinding[] parameterTypes = method.getParameterTypes(); String[] parameterNames = getParameterNames(method); int parameterTypesCount = parameterTypes.length; for (int i = 0; i < parameterTypesCount; ++i) { boolean isLastParameter = i == parameterTypesCount - 1; parameters.add(new EclipseJavaValueParameter( parameterTypes[i], method.getParameterAnnotations(i), parameterNames[i], isLastParameter ? method.isVarargs() : false)); } return parameters; } @NotNull private static String[] getParameterNames(@NotNull IMethodBinding methodBinding) { try { IMethod methodElement = (IMethod) methodBinding.getJavaElement(); String[] parameterNames; if (methodElement != null && methodElement.exists()) { parameterNames = methodElement.getParameterNames(); } else { int parametersCount = methodBinding.getParameterTypes().length; parameterNames = new String[parametersCount]; for (int i = 0; i < parametersCount; ++i) { parameterNames[i] = "arg" + i; } } return parameterNames; } catch (JavaModelException e) { KotlinLogger.logAndThrow(e); } throw new RuntimeException(); } public static JavaAnnotation findAnnotation(@NotNull IAnnotationBinding[] annotationBindings, @NotNull FqName fqName) { for (IAnnotationBinding annotation : annotationBindings) { String annotationFQName = annotation.getAnnotationType().getQualifiedName(); if (fqName.asString().equals(annotationFQName)) { return new EclipseJavaAnnotation(annotation); } } return null; } @Nullable public static ClassId computeClassId(@NotNull ITypeBinding classBinding) { ITypeBinding container = classBinding.getDeclaringClass(); if (container != null) { ClassId parentClassId = computeClassId(container); return parentClassId == null ? null : parentClassId.createNestedClassId(Name.identifier(classBinding.getName())); } String fqName = classBinding.getQualifiedName(); return fqName == null ? null : ClassId.topLevel(new FqName(fqName)); } public static boolean isKotlinLightClass(@NotNull IJavaElement element) { IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(element.getPath()); if (resource == null) { return false; } return isFromKotlinBinFolder(resource); } public static boolean isFromKotlinBinFolder(@NotNull IResource resource) { IContainer parent = resource.getParent(); while (parent != null) { if (KotlinFileSystem.SCHEME.equals(parent.getLocationURI().getScheme())) { return true; } parent = parent.getParent(); } return false; } public static boolean isFromKotlinBinFolder(@NotNull IJavaElement element) { IClassFile classFile; if (element instanceof IClassFile) { classFile = (IClassFile) element; } else if (element instanceof BinaryType) { classFile = ((BinaryType) element).getClassFile(); } else if(element instanceof BinaryMethod) { classFile = ((BinaryMethod) element).getClassFile(); } else { return false; } return classFile.getResource() == null || isFromKotlinBinFolder(classFile.getResource()); } public static boolean isKotlinBinaryElement(@NotNull IJavaElement element) { IClassFile classFile; if (element instanceof IClassFile) { classFile = (IClassFile) element; } else if (element instanceof BinaryType) { classFile = ((BinaryType) element).getClassFile(); } else { return false; } return isKotlinClassFile(classFile); } private static boolean isKotlinClassFile(IClassFile classFile) { IPath classFilePath = ProjectUtils.convertToGlobalPath(classFile.getPath()); if (classFilePath == null) { return false; } VirtualFile virtualFile = jarFileOrDirectoryToVirtualFile(classFilePath.toFile()); if (virtualFile == null) return false; String relativePath = classFile.getType().getFullyQualifiedName().replace('.', '/') + ".class"; VirtualFile archiveRelativeFile = virtualFile.findFileByRelativePath(relativePath); if (archiveRelativeFile == null) { return false; } KotlinClassFinder.Result binaryClass = KotlinBinaryClassCache.Companion.getKotlinBinaryClassOrClassFileContent(archiveRelativeFile, null); if (binaryClass == null) { return false; } if (classFile instanceof ClassFile) { try { IBinaryAnnotation[] annotations = ((ClassFile) classFile).getBinaryTypeInfo().getAnnotations(); if (annotations != null) { for (IBinaryAnnotation info : annotations) { if (Arrays.equals(info.getTypeName(), "Lkotlin/Metadata;".toCharArray())) return true; } } } catch (JavaModelException ignored) { } } return false; } @Nullable private static VirtualFile jarFileOrDirectoryToVirtualFile(@NotNull File file) { if (ApplicationManager.getApplication() == null) return null; if (file.exists()) { if (file.isDirectory()) { return VirtualFileManager.getInstance() .findFileByUrl("file://" + FileUtil.toSystemIndependentName(file.getAbsolutePath())); } else { return VirtualFileManager.getInstance().findFileByUrl("jar://" + FileUtil.toSystemIndependentName(file.getAbsolutePath()) + "!/"); } } else { throw new IllegalStateException("Path " + file + " does not exist."); } } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaField.kt ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.java.structure import org.eclipse.jdt.core.dom.IVariableBinding import org.jetbrains.kotlin.load.java.structure.JavaClass import org.jetbrains.kotlin.load.java.structure.JavaField import org.jetbrains.kotlin.load.java.structure.JavaType public class EclipseJavaField(private val javaField: IVariableBinding) : EclipseJavaMember(javaField), JavaField { override val hasConstantNotNullInitializer: Boolean get() = false override val initializerValue: Any? = binding.constantValue override val isEnumEntry: Boolean = binding.isEnumConstant() override val type: JavaType get() = EclipseJavaType.create(binding.getType()) override val containingClass: JavaClass get() = EclipseJavaClass(binding.getDeclaringClass()) } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaLiteralAnnotationArgument.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.java.structure; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.load.java.structure.JavaLiteralAnnotationArgument; import org.jetbrains.kotlin.name.Name; public class EclipseJavaLiteralAnnotationArgument implements JavaLiteralAnnotationArgument { private final Object value; private final Name name; public EclipseJavaLiteralAnnotationArgument(@NotNull Object value, @NotNull Name name) { this.value = value; this.name = name; } @Override @Nullable public Name getName() { return name; } @Override @Nullable public Object getValue() { return value; } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaMember.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.java.structure; import static org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaElementFactory.annotations; import java.lang.reflect.Modifier; import java.util.Collection; import org.eclipse.jdt.core.dom.IBinding; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.descriptors.Visibility; import org.jetbrains.kotlin.load.java.structure.JavaAnnotation; import org.jetbrains.kotlin.load.java.structure.JavaMember; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.Name; public abstract class EclipseJavaMember extends EclipseJavaElement implements JavaMember { protected EclipseJavaMember(@NotNull T javaElement) { super(javaElement); } @Override @NotNull public Collection getAnnotations() { return annotations(getBinding().getAnnotations()); } @Override @Nullable public JavaAnnotation findAnnotation(@NotNull FqName fqName) { return EclipseJavaElementUtil.findAnnotation(getBinding().getAnnotations(), fqName); } @Override public boolean isAbstract() { return Modifier.isAbstract(getBinding().getModifiers()); } @Override public boolean isStatic() { return Modifier.isStatic(getBinding().getModifiers()); } @Override public boolean isFinal() { return Modifier.isFinal(getBinding().getModifiers()); } @Override @NotNull public Visibility getVisibility() { return EclipseJavaElementUtil.getVisibility(getBinding()); } @Override @NotNull public Name getName() { return Name.identifier(getBinding().getName()); } @Override public boolean isDeprecatedInJavaDoc() { return getBinding().isDeprecated(); } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaMethod.kt ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.jetbrains.kotlin.core.resolve.lang.java.structure import org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaElementFactory.typeParameters import org.eclipse.jdt.core.dom.IMethodBinding import org.jetbrains.kotlin.load.java.structure.JavaAnnotationArgument import org.jetbrains.kotlin.load.java.structure.JavaClass import org.jetbrains.kotlin.load.java.structure.JavaMethod import org.jetbrains.kotlin.load.java.structure.JavaType import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter import org.jetbrains.kotlin.load.java.structure.JavaValueParameter import org.jetbrains.kotlin.name.Name class EclipseJavaMethod(method: IMethodBinding) : EclipseJavaMember(method), JavaMethod { override val typeParameters: List get() = typeParameters(binding.typeParameters) override val valueParameters: List get() = EclipseJavaElementUtil.getValueParameters(binding) override val annotationParameterDefaultValue: JavaAnnotationArgument? get() = with(binding) { defaultValue?.let { EclipseJavaAnnotationArgument.create(defaultValue, Name.identifier(name), javaElement.javaProject) } } override val returnType: JavaType get() = EclipseJavaType.create(binding.returnType) override val containingClass: JavaClass get() = EclipseJavaClass(binding.declaringClass) } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaPackage.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.java.structure; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import org.eclipse.jdt.core.IClassFile; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaModelException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.core.log.KotlinLogger; import org.jetbrains.kotlin.core.resolve.lang.java.EclipseJavaClassFinder; import org.jetbrains.kotlin.load.java.structure.JavaAnnotation; import org.jetbrains.kotlin.load.java.structure.JavaClass; import org.jetbrains.kotlin.load.java.structure.JavaElement; import org.jetbrains.kotlin.load.java.structure.JavaPackage; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.Name; import kotlin.jvm.functions.Function1; public class EclipseJavaPackage implements JavaElement, JavaPackage { private final List packages = new ArrayList<>(); private final IJavaProject javaProject; public EclipseJavaPackage(List packages) { this.packages.addAll(packages); this.javaProject = packages.get(0).getJavaProject(); } public EclipseJavaPackage(IPackageFragment pckg) { this(Collections.singletonList(pckg)); } @Override @NotNull public Collection getClasses(@NotNull Function1 nameFilter) { List javaClasses = new ArrayList<>(); for (IPackageFragment pckg : packages) { javaClasses.addAll(getClassesInPackage(pckg, nameFilter)); } return javaClasses; } @Override @NotNull public Collection getSubPackages() { String thisPackageName = getFqName().asString(); String pattern = thisPackageName.isEmpty() ? "*" : thisPackageName + "."; IPackageFragment[] packageFragments = EclipseJavaClassFinder.findPackageFragments( javaProject, pattern, true, true); int thisNestedLevel = thisPackageName.split("\\.").length; List javaPackages = new ArrayList<>(); if (packageFragments != null && packageFragments.length > 0) { for (IPackageFragment packageFragment : packageFragments) { int subNestedLevel = packageFragment.getElementName().split("\\.").length; boolean applicableForRootPackage = thisNestedLevel == 1 && thisNestedLevel == subNestedLevel; if (!packageFragment.getElementName().isEmpty() && (applicableForRootPackage || (thisNestedLevel + 1 == subNestedLevel))) { javaPackages.add(new EclipseJavaPackage(packageFragment)); } } } return javaPackages; } @Override @NotNull public FqName getFqName() { return new FqName(packages.get(0).getElementName()); // They all should have same names } private List getClassesInPackage(IPackageFragment javaPackage, Function1 nameFilter) { try { List javaClasses = new ArrayList<>(); for (IClassFile classFile : javaPackage.getClassFiles()) { IType type = classFile.getType(); if (isOuterClass(classFile)) { String elementName = type.getElementName(); if (Name.isValidIdentifier(elementName) && nameFilter.invoke(Name.identifier(elementName))) { javaClasses.add(new EclipseOptimizedJavaClass(type)); } } } for (ICompilationUnit cu : javaPackage.getCompilationUnits()) { for (IType javaClass : cu.getAllTypes()) { String elementName = javaClass.getElementName(); if (Name.isValidIdentifier(elementName) && nameFilter.invoke(Name.identifier(elementName))) { javaClasses.add(new EclipseOptimizedJavaClass(javaClass)); } } } return javaClasses; } catch (JavaModelException e) { KotlinLogger.logAndThrow(e); throw new IllegalStateException(e); } } // TODO: Add correct resolve binding for all class files with $ private boolean isOuterClass(IClassFile classFile) { return !classFile.getElementName().contains("$"); } @Override @Nullable public JavaAnnotation findAnnotation(@NotNull FqName arg0) { return null; } @Override @NotNull public Collection getAnnotations() { return Collections.emptyList(); } @Override public boolean isDeprecatedInJavaDoc() { return false; } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaPrimitiveType.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.java.structure; import org.eclipse.jdt.core.dom.ITypeBinding; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.PrimitiveType; import org.jetbrains.kotlin.load.java.structure.JavaPrimitiveType; import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType; public class EclipseJavaPrimitiveType extends EclipseJavaType implements JavaPrimitiveType { public EclipseJavaPrimitiveType(ITypeBinding typeBinding) { super(typeBinding); } @Override @Nullable public PrimitiveType getType() { String text = getBinding().getName(); return "void".equals(text) ? null : JvmPrimitiveType.get(text).getPrimitiveType(); } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaPropertyInitializerEvaluator.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.java.structure; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.descriptors.PropertyDescriptor; import org.jetbrains.kotlin.load.java.components.JavaPropertyInitializerEvaluator; import org.jetbrains.kotlin.load.java.structure.JavaField; import org.jetbrains.kotlin.resolve.constants.ConstantValue; import org.jetbrains.kotlin.resolve.constants.ConstantValueFactory; public class EclipseJavaPropertyInitializerEvaluator implements JavaPropertyInitializerEvaluator { @Override @Nullable public ConstantValue getInitializerConstant(@NotNull JavaField field, @NotNull PropertyDescriptor descriptor) { Object evaluated = field.getInitializerValue(); if (evaluated == null) return null; // Note: evaluated expression may be of class that does not match field type in // some cases // tested for Int, left other checks just in case if (evaluated instanceof Byte || evaluated instanceof Short || evaluated instanceof Integer || evaluated instanceof Long) return ConstantValueFactory.INSTANCE.createIntegerConstantValue(((Number) evaluated).longValue(), descriptor.getType(), false); else return ConstantValueFactory.INSTANCE.createConstantValue(evaluated); } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaReferenceAnnotationArgument.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.java.structure; import org.eclipse.jdt.core.dom.IVariableBinding; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.load.java.structure.JavaEnumValueAnnotationArgument; import org.jetbrains.kotlin.load.java.structure.JavaField; import org.jetbrains.kotlin.name.ClassId; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.Name; public class EclipseJavaReferenceAnnotationArgument extends EclipseJavaAnnotationArgument implements JavaEnumValueAnnotationArgument { protected EclipseJavaReferenceAnnotationArgument(IVariableBinding javaElement) { super(javaElement); } @Nullable public JavaField resolve() { return new EclipseJavaField(getBinding()); } @Override @Nullable public Name getEntryName() { return Name.identifier(getBinding().getName()); } @Override @Nullable public ClassId getEnumClassId() { String className = getBinding().getType().getQualifiedName(); return ClassId.topLevel(new FqName(className)); } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaType.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.java.structure; import static org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaElementFactory.annotations; import java.util.Collection; import org.eclipse.jdt.core.dom.ITypeBinding; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.load.java.structure.JavaAnnotation; import org.jetbrains.kotlin.load.java.structure.JavaAnnotationOwner; import org.jetbrains.kotlin.load.java.structure.JavaType; import org.jetbrains.kotlin.name.FqName; public class EclipseJavaType implements JavaType, JavaAnnotationOwner { private final T binding; public EclipseJavaType(@NotNull T binding) { this.binding = binding; } public static EclipseJavaType create(@NotNull ITypeBinding typeBinding) { if (typeBinding.isPrimitive()) { return new EclipseJavaPrimitiveType(typeBinding); } else if (typeBinding.isArray()) { return new EclipseJavaArrayType(typeBinding); } else if (typeBinding.isClass() || typeBinding.isTypeVariable() || typeBinding.isInterface() || typeBinding.isParameterizedType() || typeBinding.isEnum()) { return new EclipseJavaClassifierType(typeBinding); } else if (typeBinding.isWildcardType()) { return new EclipseJavaWildcardType(typeBinding); } else { throw new UnsupportedOperationException("Unsupported EclipseType: " + typeBinding); } } @NotNull public T getBinding() { return binding; } @Override public int hashCode() { return getBinding().hashCode(); } @Override public boolean equals(Object obj) { return obj instanceof EclipseJavaType && getBinding().equals(((EclipseJavaType) obj).getBinding()); } @Override @NotNull public Collection getAnnotations() { return annotations(getBinding().getAnnotations()); } @Override @Nullable public JavaAnnotation findAnnotation(@NotNull FqName fqName) { return EclipseJavaElementUtil.findAnnotation(getBinding().getAnnotations(), fqName); } @Override public boolean isDeprecatedInJavaDoc() { return binding.isDeprecated(); } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaTypeAsAnnotationArgument.kt ================================================ package org.jetbrains.kotlin.core.resolve.lang.java.structure import org.eclipse.jdt.core.dom.ITypeBinding import org.jetbrains.kotlin.load.java.structure.JavaClassObjectAnnotationArgument import org.jetbrains.kotlin.load.java.structure.JavaType import org.jetbrains.kotlin.name.Name public class EclipseJavaTypeAsAnnotationArgument(binding: ITypeBinding, override val name: Name?) : EclipseJavaAnnotationArgument(binding), JavaClassObjectAnnotationArgument { override fun getReferencedType(): JavaType { return EclipseJavaType(binding) } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaTypeParameter.kt ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.java.structure import org.eclipse.jdt.core.dom.IMethodBinding import org.eclipse.jdt.core.dom.ITypeBinding import org.jetbrains.kotlin.load.java.structure.JavaClassifierType import org.jetbrains.kotlin.load.java.structure.JavaType import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter import org.jetbrains.kotlin.load.java.structure.JavaTypeParameterListOwner import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.SpecialNames public class EclipseJavaTypeParameter(binding: ITypeBinding) : EclipseJavaClassifier(binding), JavaTypeParameter { override val name: Name = SpecialNames.safeIdentifier(binding.getName()) override val upperBounds: Collection get() = binding.getTypeBounds().map(::EclipseJavaClassifierType) } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaValueParameter.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.java.structure; import static org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaElementFactory.annotations; import java.util.Arrays; import java.util.Collection; import org.eclipse.jdt.core.dom.IAnnotationBinding; import org.eclipse.jdt.core.dom.ITypeBinding; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.load.java.structure.JavaAnnotation; import org.jetbrains.kotlin.load.java.structure.JavaType; import org.jetbrains.kotlin.load.java.structure.JavaValueParameter; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.Name; public class EclipseJavaValueParameter extends EclipseJavaElement implements JavaValueParameter { private final String name; private final boolean isVararg; private final IAnnotationBinding[] annotationBindings; public EclipseJavaValueParameter(ITypeBinding type, IAnnotationBinding annotationBindings[], String name, boolean isVararg) { super(type); this.name = name; this.isVararg = isVararg; this.annotationBindings = Arrays.copyOf(annotationBindings, annotationBindings.length); } @Override @NotNull public Collection getAnnotations() { return annotations(annotationBindings); } @Override @Nullable public JavaAnnotation findAnnotation(@NotNull FqName fqName) { return EclipseJavaElementUtil.findAnnotation(annotationBindings, fqName); } @Override @Nullable public Name getName() { return Name.identifier(name); } @Override @NotNull public JavaType getType() { return EclipseJavaType.create(getBinding()); } @Override public boolean isVararg() { return isVararg; } @Override public boolean isDeprecatedInJavaDoc() { return getBinding().isDeprecated(); } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseJavaWildcardType.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.java.structure; import org.eclipse.jdt.core.dom.ITypeBinding; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.load.java.structure.JavaType; import org.jetbrains.kotlin.load.java.structure.JavaWildcardType; public class EclipseJavaWildcardType extends EclipseJavaType implements JavaWildcardType { public EclipseJavaWildcardType(@NotNull ITypeBinding typeBinding) { super(typeBinding); } @Override @Nullable public JavaType getBound() { ITypeBinding bound = getBinding().getBound(); return bound != null ? EclipseJavaType.create(bound) : null; } @Override public boolean isExtends() { return getBinding().isUpperbound(); } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/java/structure/EclipseOptimizedJavaClass.kt ================================================ package org.jetbrains.kotlin.core.resolve.lang.java.structure import org.eclipse.jdt.core.IType import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.descriptors.Visibility import org.jetbrains.kotlin.core.resolve.lang.java.EclipseJavaClassFinder import org.jetbrains.kotlin.load.java.structure.* class EclipseOptimizedJavaClass(val eclipseClass: IType) : JavaClass { override val name: Name get() = SpecialNames.safeIdentifier(eclipseClass.getElementName()) override val constructors: Collection get() = throw UnsupportedOperationException() override val fields: Collection get() = throw UnsupportedOperationException() override val fqName: FqName? get() = throw UnsupportedOperationException() override val innerClassNames: Collection get() = throw UnsupportedOperationException() override fun findInnerClass(name: Name): JavaClass? { throw UnsupportedOperationException() } override val isAnnotationType: Boolean get() = throw UnsupportedOperationException() override val isEnum: Boolean get() = throw UnsupportedOperationException() override val isInterface: Boolean get() = throw UnsupportedOperationException() override val isRecord: Boolean get() = throw UnsupportedOperationException() override val isSealed: Boolean get() = throw UnsupportedOperationException() override val lightClassOriginKind: LightClassOriginKind? get() = if (EclipseJavaElementUtil.isKotlinLightClass(eclipseClass)) LightClassOriginKind.SOURCE else null override val methods: Collection get() = throw UnsupportedOperationException() override val outerClass: JavaClass? get() = throw UnsupportedOperationException() override val permittedTypes: Collection get() = throw UnsupportedOperationException() override val recordComponents: Collection get() = throw UnsupportedOperationException() override val supertypes: Collection get() = throw UnsupportedOperationException() override val annotations: Collection get() = throw UnsupportedOperationException() override val isDeprecatedInJavaDoc: Boolean get() = throw UnsupportedOperationException() override fun findAnnotation(fqName: FqName): JavaAnnotation? { throw UnsupportedOperationException() } override val typeParameters: List get() = throw UnsupportedOperationException() override val isAbstract: Boolean get() = throw UnsupportedOperationException() override val isFinal: Boolean get() = throw UnsupportedOperationException() override val isStatic: Boolean get() = throw UnsupportedOperationException() override val visibility: Visibility get() = throw UnsupportedOperationException() override fun hasDefaultConstructor() = throw UnsupportedOperationException() } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/lang/kotlin/EclipseVirtualFileFinder.kt ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.lang.kotlin import com.intellij.openapi.vfs.VirtualFile import com.intellij.psi.search.GlobalSearchScope import org.eclipse.jdt.core.IJavaProject import org.eclipse.jdt.core.IType import org.eclipse.jdt.internal.compiler.util.Util.isClassFileName import org.jetbrains.kotlin.serialization.deserialization.builtins.BuiltInSerializerProtocol import org.jetbrains.kotlin.cli.jvm.index.JavaRoot import org.jetbrains.kotlin.core.model.KotlinEnvironment import org.jetbrains.kotlin.core.resolve.lang.java.EclipseJavaClassFinder import org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaClassifier import org.jetbrains.kotlin.core.resolve.lang.java.structure.EclipseJavaElementUtil import org.jetbrains.kotlin.load.java.structure.JavaClass import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.serialization.deserialization.MetadataPackageFragment import java.io.InputStream import org.jetbrains.kotlin.cli.jvm.index.JvmDependenciesIndex import org.jetbrains.kotlin.load.kotlin.* import com.intellij.openapi.project.Project import org.jetbrains.kotlin.descriptors.ModuleDescriptor class EclipseVirtualFileFinder( private val javaProject: IJavaProject, private val scope: GlobalSearchScope) : VirtualFileFinder() { private val index: JvmDependenciesIndex get() = KotlinEnvironment.getEnvironment(javaProject.project).index override fun findMetadata(classId: ClassId): InputStream? { assert(!classId.isNestedClass) { "Nested classes are not supported here: $classId" } return findBinaryClass( classId, classId.shortClassName.asString() + MetadataPackageFragment.DOT_METADATA_FILE_EXTENSION)?.inputStream } override fun findSourceOrBinaryVirtualFile(classId: ClassId): VirtualFile? = findVirtualFileWithHeader(classId) override fun hasMetadataPackage(fqName: FqName): Boolean { var found = false val index = KotlinEnvironment.getEnvironment(javaProject.project).index index.traverseDirectoriesInPackage(fqName, continueSearch = { dir, _ -> found = found or dir.children.any { it.extension == MetadataPackageFragment.METADATA_FILE_EXTENSION } !found }) return found } override fun findBuiltInsData(packageFqName: FqName): InputStream? { val fileName = BuiltInSerializerProtocol.getBuiltInsFileName(packageFqName) // "" is just a made-up name // JvmDependenciesIndex requires the ClassId of the class which we're searching for, to cache the last request+result val classId = ClassId(packageFqName, Name.special("")) return index.findClass(classId, acceptedRootTypes = JavaRoot.OnlyBinary) { dir, _ -> dir.findChild(fileName)?.check(VirtualFile::isValid) }?.check { it in scope && it.isValid }?.inputStream } override fun findVirtualFileWithHeader(classId: ClassId): VirtualFile? { val type = javaProject.findType(classId.packageFqName.asString(), classId.relativeClassName.asString()) if (type == null || !isBinaryKotlinClass(type)) return null val resource = type.resource // if resource != null then it exists in the workspace and then get absolute path val path = if (resource != null) resource.location else type.path val eclipseProject = javaProject.project // In the classpath we can have either path to jar file ot to the class folder // Therefore in path might be location to the jar file or to the class file return when { isClassFileName(path.toOSString()) -> KotlinEnvironment.getEnvironment(eclipseProject).getVirtualFile(path) KotlinEnvironment.getEnvironment(eclipseProject).isJarFile(path) -> { val relativePath = "${type.fullyQualifiedName.replace('.', '/')}.class" KotlinEnvironment.getEnvironment(eclipseProject).getVirtualFileInJar(path, relativePath) } else -> throw IllegalArgumentException("Virtual file not found for $path") } } private fun isBinaryKotlinClass(type: IType): Boolean = type.isBinary && !EclipseJavaClassFinder.isInKotlinBinFolder(type) private fun classFileName(jClass:JavaClass): String { val outerClass = jClass.outerClass if (outerClass == null) return jClass.name.asString() return classFileName(outerClass) + "$" + jClass.name.asString() } private fun findBinaryClass(classId: ClassId, fileName: String): VirtualFile? = index.findClass(classId, acceptedRootTypes = JavaRoot.OnlyBinary) { dir, rootType -> dir.findChild(fileName)?.check(VirtualFile::isValid) }?.check { it in scope } override fun findKotlinClassOrContent(javaClass: JavaClass): KotlinClassFinder.Result? { val fqName = javaClass.fqName ?: return null if (fqName == null) return null val classId = EclipseJavaElementUtil.computeClassId((javaClass as EclipseJavaClassifier<*>).binding) ?: return null if (classId == null) return null var file = findVirtualFileWithHeader(classId) if (file == null) return null if (javaClass.outerClass != null) { // For nested classes we get a file of the containing class, to get the actual class file for A.B.C, // we take the file for A, take its parent directory, then in this directory we look for A$B$C.class file = file.getParent().findChild("${classFileName(javaClass)}.class") if (file != null) throw IllegalStateException("Virtual file not found for $javaClass") } return KotlinBinaryClassCache.getKotlinBinaryClassOrClassFileContent(file!!) } } class EclipseVirtualFileFinderFactory(private val project: IJavaProject) : VirtualFileFinderFactory { override fun create(_project: Project, module: ModuleDescriptor) = EclipseVirtualFileFinder(project, GlobalSearchScope.allScope(_project)) override fun create(scope: GlobalSearchScope): VirtualFileFinder = EclipseVirtualFileFinder(project, scope) } fun T.check(predicate: (T) -> Boolean): T? = if (predicate(this)) this else null ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/resolve/sources/LibrarySourcesIndex.kt ================================================ /******************************************************************************* * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.resolve.sources import java.util.HashMap import org.eclipse.jdt.core.IPackageFragmentRoot import java.util.zip.ZipFile import org.eclipse.core.runtime.Path import java.util.ArrayList import org.eclipse.jdt.core.IPackageFragment import java.util.zip.ZipEntry import java.io.BufferedInputStream import java.io.InputStreamReader import java.io.BufferedReader import org.jetbrains.kotlin.core.resolve.KotlinSourceIndex import kotlin.io.use import org.eclipse.core.resources.ResourcesPlugin import org.jetbrains.kotlin.core.utils.ProjectUtils import org.eclipse.core.runtime.IPath import java.io.File fun getSourcePath(root: IPackageFragmentRoot): IPath? { return ProjectUtils.convertToGlobalPath(root.resolvedClasspathEntry?.sourceAttachmentPath) } class LibrarySourcesIndex(private val jarWithSources: File) { private val index = hashMapOf>() private val PACKAGE_LINE_PREFIX = "package " init { if (!jarWithSources.exists()) { throw IllegalArgumentException("File with sources ($jarWithSources) should exist") } val sourceArchive = ZipFile(jarWithSources) sourceArchive.entries().toList() .map { it.getName() } .filter { KotlinSourceIndex.isKotlinSource(it) } .forEach { val shortName = Path(it).lastSegment() index.getOrPut(shortName) { ArrayList() }.add(SourceFile(it)) } } fun resolve(shortName: String, packageFolder: IPath): String? { val packageFqName = packageFolder.segments().joinToString(".") return resolve(shortName, packageFqName) } fun resolve(shortName: String, packageFqName: String): String? { val sourcesList = index[shortName] ?: return null if (sourcesList.size == 1) { return sourcesList.first().path } val sourceArchive = ZipFile(jarWithSources) for (it in sourcesList) { if (it.effectivePackage == null) { it.effectivePackage = getPackageName(sourceArchive, sourceArchive.getEntry(it.path)) } } return sourcesList .filter { packageFqName == it.effectivePackage } .singleOrNull() ?.path } private fun getPackageName(zipFile: ZipFile, entry: ZipEntry): String? { val istream = zipFile.getInputStream(entry) val reader = BufferedReader(InputStreamReader(istream)) return reader.use { it.lineSequence() .firstOrNull { it.startsWith(PACKAGE_LINE_PREFIX) } ?.removePrefix(PACKAGE_LINE_PREFIX) ?.trim() } } } private class SourceFile(val path: String, var effectivePackage: String? = null) ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/script/EnvironmentProjectsManager.kt ================================================ package org.jetbrains.kotlin.core.script import org.eclipse.core.internal.resources.ProjectDescription import org.eclipse.core.resources.ResourcesPlugin import org.eclipse.jdt.core.IJavaProject import org.eclipse.jdt.core.JavaCore import org.jetbrains.kotlin.core.model.KotlinNature import org.jetbrains.kotlin.core.utils.withResourceLock import org.jetbrains.kotlin.psi.KtFile import java.net.URI import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentMap object EnvironmentProjectsManager { private val projectCache: ConcurrentMap = ConcurrentHashMap() private val createdProjects = mutableSetOf() operator fun get(scriptFile: KtFile) = projectCache.getOrPut(scriptFile.virtualFilePath) { withResourceLock(ResourcesPlugin.getWorkspace().root) { root -> nameCandidates(scriptFile).map { root.getProject(it) } .first { !it.exists() } .run { createdProjects += name val description = ProjectDescription().apply { name = this@run.name locationURI = URI.create("org.jetbrains.kotlin.script:/environments/${this@run.name}") natureIds = arrayOf(JavaCore.NATURE_ID) } create(description, null) open(null) KotlinNature.addNature(this) isHidden = true JavaCore.create(this) } } } fun wasCreated(name: String) = name in createdProjects private fun nameCandidates(scriptFile: KtFile): Sequence = generateSequence(1) { it + 1 } .map { n -> listOfNotNull( scriptFile.packageFqName.takeUnless { it.isRoot }, scriptFile.name, n.takeIf { it > 1 }?.toString() ).joinToString("-") } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/script/ScriptTemplateContribution.kt ================================================ package org.jetbrains.kotlin.core.script import org.eclipse.jdt.core.IClasspathEntry import org.jetbrains.kotlin.core.model.KotlinScriptEnvironment import java.io.File import kotlin.reflect.KClass import kotlin.script.experimental.api.ScriptCompilationConfiguration abstract class ScriptTemplateContribution { open val priority = 0 protected abstract fun loadTemplate(): KClass<*> open fun createClasspath(environment: KotlinScriptEnvironment): Array = environment.javaProject.rawClasspath val template by lazy { loadTemplate() } open fun isNullable(propName: String, compilationConfig: ScriptCompilationConfiguration): Boolean = true open fun scriptEnvironment(script: File): Map = emptyMap() } abstract class JavaScriptTemplateContribution : ScriptTemplateContribution() { abstract val javaClass: Class<*> override fun loadTemplate(): KClass<*> = javaClass.kotlin } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/script/template/ProjectFilesResolver.kt ================================================ package org.jetbrains.kotlin.core.script.template import java.io.File import kotlin.script.dependencies.Environment import kotlin.script.dependencies.ScriptContents import kotlin.script.experimental.dependencies.DependenciesResolver import kotlin.script.experimental.dependencies.ScriptDependencies import kotlin.script.experimental.dependencies.asSuccess class ProjectFilesResolver : DependenciesResolver { override fun resolve(scriptContents: ScriptContents, environment: Environment): DependenciesResolver.ResolveResult { val classpath = (environment["eclipseProjectClasspath"] as? String) ?.split(":") ?.map { File(it) } .orEmpty() return ScriptDependencies(classpath = classpath).asSuccess() } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/script/template/ProjectScriptTemplate.kt ================================================ package org.jetbrains.kotlin.core.script.template import kotlin.script.templates.ScriptTemplateDefinition @ScriptTemplateDefinition(resolver = ProjectFilesResolver::class) abstract class ProjectScriptTemplate(val args: Array) ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/script/template/ProjectScriptTemplateContribution.kt ================================================ /* * Copyright 2019 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. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jetbrains.kotlin.core.script.template import org.eclipse.core.resources.IFile import org.eclipse.core.runtime.Path import org.eclipse.jdt.core.IClasspathEntry import org.eclipse.jdt.core.JavaCore import org.jetbrains.kotlin.core.model.KotlinScriptEnvironment import org.jetbrains.kotlin.core.script.ScriptTemplateContribution import org.jetbrains.kotlin.core.utils.* import java.io.File class ProjectScriptTemplateContribution : ScriptTemplateContribution() { override val priority: Int get() = Int.MAX_VALUE override fun loadTemplate() = ProjectScriptTemplate::class override fun scriptEnvironment(script: File): Map { val file = script.asResource val definitionClasspath = file?.let { KotlinScriptEnvironment.getEnvironment(file) } ?.definitionClasspath.orEmpty() val projectClasspath = projectClasspathForScript(file) val allClasspath = (projectClasspath + definitionClasspath) .joinToString(separator = ":") { it.absolutePath } return mapOf("eclipseProjectClasspath" to allClasspath) } private fun projectClasspathForScript(file: IFile?): List { if (file == null) return emptyList() val javaProject = file.javaProject ?: return emptyList() if (!file.isInClasspath) return emptyList() val projectClasspath = try { ProjectUtils.collectClasspathWithDependenciesForLaunch(javaProject, false) } catch (e: DependencyResolverException) { e.resolvedFiles } val outputFolders = ProjectUtils.getAllOutputFolders(javaProject).map { it.location.toFile() } return projectClasspath + outputFolders } override fun createClasspath(environment: KotlinScriptEnvironment): Array = (environment.javaProject.rawClasspath + environment.definitionClasspath.map { JavaCore.newLibraryEntry(Path(it.absolutePath), null, null) }).distinctBy { it.path }.toTypedArray() } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/DebugUtils.java ================================================ package org.jetbrains.kotlin.core.utils; import java.util.Optional; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.model.IStackFrame; import org.eclipse.debug.core.model.IVariable; import org.eclipse.jdt.debug.core.IJavaStackFrame; import org.jetbrains.kotlin.core.log.KotlinLogger; public class DebugUtils { public static Boolean isVisible(IVariable variable) { try { return !variable.getName().startsWith("$i$"); } catch (Exception e) { KotlinLogger.logError(e); return false; } } public static Boolean hasKotlinSource(IStackFrame frame) throws DebugException { if (frame instanceof IJavaStackFrame) { IJavaStackFrame javaFrame = (IJavaStackFrame) frame; return Optional.ofNullable(javaFrame.getSourceName()).map(s -> s.endsWith(".kt")).orElse(false); } else { return false; } } } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/DependencyResolverException.kt ================================================ package org.jetbrains.kotlin.core.utils import java.io.File class DependencyResolverException(val resolvedFiles: List) : RuntimeException() ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/ProjectUtils.kt ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.jetbrains.kotlin.core.utils import org.eclipse.core.resources.* import org.eclipse.core.runtime.* 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.launching.JavaRuntime import org.jetbrains.kotlin.core.KotlinClasspathContainer import org.jetbrains.kotlin.core.builder.KotlinPsiManager import org.jetbrains.kotlin.core.log.KotlinLogger import org.jetbrains.kotlin.core.model.KotlinNature import org.jetbrains.kotlin.psi.KtFile import java.io.File object ProjectUtils { private const val LIB_FOLDER = "lib" private const val LIB_EXTENSION = "jar" private const val MAVEN_NATURE_ID = "org.eclipse.m2e.core.maven2Nature" private const val GRADLE_NATURE_ID = "org.eclipse.buildship.core.gradleprojectnature" val accessibleKotlinProjects: List get() = ResourcesPlugin.getWorkspace().root.projects.filter { project -> isAccessibleKotlinProject(project) } @JvmStatic val ktHome: String by lazy { val compilerBundle = Platform.getBundle("org.jetbrains.kotlin.bundled-compiler") FileLocator.toFileURL(compilerBundle.getEntry("/")).file } fun getJavaProjectFromCollection(files: Collection): IJavaProject? = files.firstOrNull() ?.let { JavaCore.create(it.project) } fun getPackageByFile(file: IFile): String? = KotlinPsiManager.getParsedFile(file).packageFqName.asString() @JvmStatic @JvmOverloads fun cleanFolder(container: IContainer?, predicate: (IResource) -> Boolean = { true }) { try { if (container == null) { return } if (container.exists()) { for (member in container.members()) { if (member is IContainer) { cleanFolder(member, predicate) } if (predicate(member)) { if (member.exists()) { member.delete(true, null) } } } } } catch (e: CoreException) { KotlinLogger.logError("Error while cleaning folder", e) } } @JvmStatic fun getDefaultOutputFolder(javaProject: IJavaProject): IFolder? = ResourcesPlugin.getWorkspace().root.findMember(javaProject.outputLocation) as? IFolder @JvmStatic fun getAllOutputFolders(javaProject: IJavaProject): List = javaProject.getResolvedClasspath(true) .asSequence() .filter { it.entryKind == IClasspathEntry.CPE_SOURCE } .map { it.outputLocation } .let { it + javaProject.outputLocation } .filterNotNull() .distinct() .mapNotNull { ResourcesPlugin.getWorkspace().root.findMember(it) as? IFolder } .filter { it.exists() } .toList() fun getSourceFiles(project: IProject): List { var tempFiles = KotlinPsiManager.getFilesByProject(project) if (tempFiles.any { !it.asFile.exists() }) { project.refreshLocal(IResource.DEPTH_INFINITE, NullProgressMonitor()) } tempFiles = KotlinPsiManager.getFilesByProject(project) return tempFiles .map { KotlinPsiManager.getParsedFile(it) } } fun getSourceFilesWithDependencies(javaProject: IJavaProject): List = (listOf(javaProject).getDependencyProjects() + javaProject.project) .flatMap { getSourceFiles(it) } fun getDependencyProjects(javaProject: IJavaProject) = listOf(javaProject).getDependencyProjects() tailrec fun Collection.getDependencyProjects(result: MutableSet = hashSetOf()): Set { if (isEmpty()) return result return flatMap { it.getResolvedClasspath(true).toList() } .asSequence() .filter { it.entryKind == IClasspathEntry.CPE_PROJECT } .map { ResourcesPlugin.getWorkspace().root.getProject(it.path.toPortableString()) } .filter { it.isAccessible } .filter { result.add(it) } .map { JavaCore.create(it) } .toList() .getDependencyProjects(result) } fun collectClasspathWithDependenciesForBuild(javaProject: IJavaProject): List { return expandClasspath(javaProject, true, false) { true } } @JvmStatic fun collectClasspathWithDependenciesForLaunch(javaProject: IJavaProject, includeJRE: Boolean): List { val jreEntries = getJREClasspathElements(javaProject) return expandClasspath(javaProject, true, true) { entry -> entry.entryKind == IClasspathEntry.CPE_LIBRARY && (includeJRE || jreEntries.none { it.path == entry.path }) } } private fun getJREClasspathElements(javaProject: IJavaProject): List = JavaRuntime.resolveRuntimeClasspathEntry(JavaRuntime.computeJREEntry(javaProject), javaProject) .map { it.classpathEntry } private fun expandClasspath( javaProject: IJavaProject, includeDependencies: Boolean, includeBinFolders: Boolean, entryPredicate: Function1 ): List { val orderedFiles = LinkedHashSet() var wasError = false for (classpathEntry in javaProject.getResolvedClasspath(true)) { if (classpathEntry.entryKind == IClasspathEntry.CPE_PROJECT && includeDependencies) { try { orderedFiles.addAll( expandDependentProjectClasspath( classpathEntry, includeBinFolders, entryPredicate ) ) } catch (e: DependencyResolverException) { wasError = true orderedFiles.addAll(e.resolvedFiles) } } else { // Source folder or library if (entryPredicate.invoke(classpathEntry)) { orderedFiles.addAll(getFileByEntry(classpathEntry, javaProject)) } } } if(wasError) { throw DependencyResolverException(orderedFiles.toList()) } return orderedFiles.toList() } fun getFileByEntry(entry: IClasspathEntry, javaProject: IJavaProject): List = javaProject.findPackageFragmentRoots(entry) .takeIf { it.isNotEmpty() } ?.map { it.resource?.location?.toFile() ?: it.path.toFile() } ?: entry.path.toFile() .takeIf { it.exists() } ?.let { listOf(it) } ?: emptyList() private fun expandDependentProjectClasspath( projectEntry: IClasspathEntry, includeBinFolders: Boolean, entryPredicate: Function1 ): List { val projectPath = projectEntry.path val dependentProject = ResourcesPlugin.getWorkspace().root.getProject(projectPath.toString()) val javaProject = JavaCore.create(dependentProject) val orderedFiles = LinkedHashSet() var wasError = false try { for (classpathEntry in javaProject.getResolvedClasspath(true)) { if (!(classpathEntry.isExported || classpathEntry.entryKind == IClasspathEntry.CPE_SOURCE)) { continue } if (classpathEntry.entryKind == IClasspathEntry.CPE_PROJECT) { try { orderedFiles.addAll( expandDependentProjectClasspath( classpathEntry, includeBinFolders, entryPredicate ) ) } catch (e: DependencyResolverException) { wasError = true orderedFiles.addAll(e.resolvedFiles) } } else { if (entryPredicate.invoke(classpathEntry)) { orderedFiles.addAll(getFileByEntry(classpathEntry, javaProject)) } } } if (includeBinFolders) { getAllOutputFolders(javaProject) .map { it.location.toFile() } .toCollection(orderedFiles) } } catch (e: JavaModelException) { throw DependencyResolverException(emptyList()) } if(wasError) { throw DependencyResolverException(orderedFiles.toList()) } return orderedFiles.toList() } @JvmStatic fun getSrcOutDirectories(javaProject: IJavaProject): List> { val projectOutput = javaProject.outputLocation val root = ResourcesPlugin.getWorkspace().root return javaProject.getResolvedClasspath(true) .filter { it.entryKind == IClasspathEntry.CPE_SOURCE } .filter { root.findMember(it.path)?.takeIf(IResource::exists) != null } .mapNotNull { cpe -> (cpe.outputLocation ?: projectOutput) ?.let { root.findMember(it) } ?.takeIf { it.exists() } ?.let { root.findMember(cpe.path).location.toFile() to it.location.toFile() } .also { if (it == null) KotlinLogger.logError( "There is no output folder for sources: ${cpe.path.toOSString()}", null ) } } } fun addToClasspath(javaProject: IJavaProject, vararg newEntries: IClasspathEntry) { javaProject.setRawClasspath(javaProject.rawClasspath + newEntries, null) } @JvmStatic fun addContainerEntryToClasspath(javaProject: IJavaProject, newEntry: IClasspathEntry) { if (!classpathContainsContainerEntry(javaProject.rawClasspath, newEntry)) { addToClasspath(javaProject, newEntry) } } fun equalsEntriesPaths(entry: IClasspathEntry, otherEntry: IClasspathEntry): Boolean { return entry.path == otherEntry.path } private fun classpathContainsContainerEntry( entries: Array, entry: IClasspathEntry ): Boolean { return entries.any { classpathEntry -> equalsEntriesPaths(classpathEntry, entry) } } fun hasKotlinRuntime(project: IProject): Boolean { return classpathContainsContainerEntry( JavaCore.create(project).rawClasspath, KotlinClasspathContainer.CONTAINER_ENTRY ) } @JvmStatic fun addKotlinRuntime(project: IProject) { addKotlinRuntime(JavaCore.create(project)) } @JvmStatic fun addKotlinRuntime(javaProject: IJavaProject) { addContainerEntryToClasspath(javaProject, KotlinClasspathContainer.CONTAINER_ENTRY) } @JvmStatic fun convertToGlobalPath(path: IPath?): IPath? { if (path == null) { return null } if (path.toFile().exists()) { return path.makeAbsolute() } else { val file = ResourcesPlugin.getWorkspace().root.getFile(path) if (file.exists()) { return file.rawLocation } } return null } fun isMavenProject(project: IProject): Boolean = project.hasNature(MAVEN_NATURE_ID) fun isGradleProject(project: IProject): Boolean = project.hasNature(GRADLE_NATURE_ID) @JvmStatic fun buildLibPath(libName: String): String = ktHome + buildLibName(libName) fun isAccessibleKotlinProject(project: IProject): Boolean = project.isAccessible && KotlinNature.hasKotlinNature(project) private fun buildLibName(libName: String): String = "$LIB_FOLDER/$libName.$LIB_EXTENSION" fun newExportedLibraryEntry(path: IPath): IClasspathEntry = JavaCore.newLibraryEntry(path, null, null, true) } fun String.buildLibPath(): Path = Path(ProjectUtils.buildLibPath(this)) ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/analyzeUtils.kt ================================================ /******************************************************************************* * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.utils import org.jetbrains.kotlin.core.resolve.KotlinAnalyzer import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.BindingContext fun KtElement.getBindingContext(): BindingContext = containingKtFile.getBindingContext() fun KtFile.getBindingContext(): BindingContext = KotlinAnalyzer.analyzeFile(this).analysisResult.bindingContext fun getModuleDescriptor(ktFile: KtFile): ModuleDescriptor = KotlinAnalyzer.analyzeFile(ktFile).analysisResult.moduleDescriptor ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/genericUtils.kt ================================================ package org.jetbrains.kotlin.core.utils fun pairOfNotNulls(first: T?, second: S?): Pair? = second?.let { first?.to(it) } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/importsUtils.kt ================================================ /******************************************************************************* * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.utils import com.intellij.psi.PsiClass import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.LanguageFeature.DefaultImportOfPackageKotlinComparisons import org.jetbrains.kotlin.config.LanguageVersion import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.idea.util.ActionRunningMode import org.jetbrains.kotlin.idea.util.ImportDescriptorResult import org.jetbrains.kotlin.idea.util.ImportInsertHelper import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.ImportPath import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatformAnalyzerServices class KotlinImportInserterHelper : ImportInsertHelper() { private val importSortComparator: Comparator = Comparator { _, _ -> 0 } override fun getImportSortComparator(contextFile: KtFile): Comparator { return importSortComparator } override fun importDescriptor( element: KtElement, descriptor: DeclarationDescriptor, actionRunningMode: ActionRunningMode, forceAllUnderImport: Boolean ): ImportDescriptorResult { throw UnsupportedOperationException() } override fun importPsiClass( element: KtElement, psiClass: PsiClass, actionRunningMode: ActionRunningMode ): ImportDescriptorResult { throw UnsupportedOperationException() } override fun isImportedWithDefault(importPath: ImportPath, contextFile: KtFile): Boolean { val defaultImports = JvmPlatformAnalyzerServices.getDefaultImports( if (LanguageVersionSettingsImpl.DEFAULT.supportsFeature(DefaultImportOfPackageKotlinComparisons)) LanguageVersionSettingsImpl.DEFAULT else LanguageVersionSettingsImpl(LanguageVersion.KOTLIN_1_0, ApiVersion.KOTLIN_1_0), true ) return importPath.isImported(defaultImports) } override fun mayImportOnShortenReferences(descriptor: DeclarationDescriptor, contextFile: KtFile): Boolean { return false } override fun isImportedWithLowPriorityDefaultImport(importPath: ImportPath, contextFile: KtFile): Boolean = isImportedWithDefault(importPath, contextFile) } // TODO: obtain these functions from fqNameUtil.kt (org.jetbrains.kotlin.idea.refactoring.fqName) fun FqName.isImported(importPath: ImportPath, skipAliasedImports: Boolean = true): Boolean { return when { skipAliasedImports && importPath.hasAlias() -> false importPath.isAllUnder && !isRoot -> importPath.fqName == this.parent() else -> importPath.fqName == this } } fun ImportPath.isImported(alreadyImported: ImportPath): Boolean { return if (isAllUnder || hasAlias()) this == alreadyImported else fqName.isImported(alreadyImported) } fun ImportPath.isImported(imports: Iterable): Boolean = imports.any { isImported(it) } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/jobUtils.kt ================================================ package org.jetbrains.kotlin.core.utils import org.eclipse.core.resources.IResource import org.eclipse.core.runtime.IProgressMonitor import org.eclipse.core.runtime.jobs.Job fun withResourceLock(resource: R, monitor: IProgressMonitor? = null, block: (R) -> T): T = try { Job.getJobManager().beginRule(resource, monitor) block(resource) } finally { Job.getJobManager().endRule(resource) } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/kotlinFilesCollectorUtils.kt ================================================ /******************************************************************************* * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.core.utils import org.eclipse.core.resources.IFile import org.eclipse.core.resources.IFolder import org.eclipse.core.resources.IResource import org.eclipse.core.resources.IResourceDelta import org.eclipse.core.runtime.CoreException import org.eclipse.jdt.core.IJavaProject import org.jetbrains.kotlin.core.builder.KotlinPsiManager import org.jetbrains.kotlin.core.log.KotlinLogger import org.eclipse.jdt.core.IPackageFragmentRoot import org.jetbrains.kotlin.core.model.KotlinNature import org.eclipse.core.resources.ResourcesPlugin import org.eclipse.jdt.core.JavaCore import org.jetbrains.kotlin.core.model.setKotlinBuilderBeforeJavaBuilder val IJavaProject.sourceFolders: List get() = packageFragmentRoots.filter { it.kind == IPackageFragmentRoot.K_SOURCE } ================================================ FILE: kotlin-eclipse-core/src/org/jetbrains/kotlin/core/utils/projectFilesUtils.kt ================================================ package org.jetbrains.kotlin.core.utils import org.eclipse.core.resources.IFile import org.eclipse.core.resources.IResource import org.eclipse.core.resources.ResourcesPlugin import org.eclipse.core.runtime.Path import org.eclipse.jdt.core.IClasspathEntry import org.eclipse.jdt.core.IJavaProject import org.eclipse.jdt.core.JavaCore import org.eclipse.jdt.internal.core.JavaProject import java.io.File val IFile.isInClasspath: Boolean get() { val project = JavaCore.create(project) as JavaProject val packageRoots = project.getResolvedClasspath(true) .asSequence() .filter { it.entryKind == IClasspathEntry.CPE_SOURCE } .flatMap { project.computePackageFragmentRoots(it).asSequence() } .map { it.resource } .toSet() return generateSequence(this) { it.parent } .any { it in packageRoots } } val File.asResource: IFile? get() = ResourcesPlugin.getWorkspace().root .getFileForLocation(Path.fromOSString(absolutePath)) val IFile.asFile: File get() = File(locationURI) val IFile.javaProject: IJavaProject? get() = project?.let { JavaCore.create(it) } ================================================ FILE: kotlin-eclipse-feature/build.properties ================================================ ############################################################################### # Copyright 2000-2014 JetBrains s.r.o. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### bin.includes = feature.xml ================================================ FILE: kotlin-eclipse-feature/feature.xml ================================================ Kotlin language support for Kotlin 1.6.21 Copyright 2010-2016 JetBrains s.r.o. Copyright 2010-2016 JetBrains s.r.o. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: kotlin-eclipse-feature/pom.xml ================================================ 4.0.0 ../pom.xml kotlin.eclipse kotlin.eclipse.plugin 0.8.24-SNAPSHOT org.jetbrains.kotlin.feature 0.8.24-SNAPSHOT eclipse-feature ================================================ FILE: kotlin-eclipse-gradle/META-INF/MANIFEST.MF ================================================ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: kotlin-eclipse-gradle Bundle-SymbolicName: org.jetbrains.kotlin.gradle;singleton:=true Bundle-Version: 0.8.24.qualifier Bundle-Activator: org.jetbrains.kotlin.gradle.Activator Bundle-Vendor: JetBrains Require-Bundle: org.jetbrains.kotlin.core, org.jetbrains.kotlin.bundled-compiler, org.eclipse.buildship.core;bundle-version="3.0.0", org.eclipse.core.runtime, org.jetbrains.kotlin.gradle.model Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-ActivationPolicy: lazy Import-Package: org.eclipse.core.resources, org.eclipse.jdt.core Export-Package: org.jetbrains.kotlin.gradle.initialization, org.jetbrains.kotlin.gradle.configurator ================================================ FILE: kotlin-eclipse-gradle/build.properties ================================================ source.. = src/ output.. = bin/ bin.includes = META-INF/,\ .,\ plugin.xml,\ scripts/ ================================================ FILE: kotlin-eclipse-gradle/plugin.xml ================================================ ================================================ FILE: kotlin-eclipse-gradle/pom.xml ================================================ 4.0.0 ../pom.xml kotlin.eclipse kotlin.eclipse.plugin 0.8.24-SNAPSHOT org.jetbrains.kotlin.gradle eclipse-plugin src org.jetbrains.kotlin kotlin-maven-plugin ${kotlin.version} 17 compile process-sources compile ================================================ FILE: kotlin-eclipse-gradle/scripts/init.gradle.kts ================================================ import javax.inject.Inject import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.tooling.provider.model.ToolingModelBuilder import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry import org.jetbrains.kotlin.gradle.model.GradleProjectForEclipse import org.jetbrains.kotlin.gradle.model.KotlinGradleProject import org.jetbrains.kotlin.gradle.model.GradleMultiProjectForEclipse import org.jetbrains.kotlin.gradle.model.GradleMultiProjectForEclipseImpl import org.jetbrains.kotlin.gradle.model.NonKotlinProject import org.jetbrains.kotlin.gradle.model.CompilerPluginConfig import org.jetbrains.kotlin.gradle.model.AllOpen import org.jetbrains.kotlin.gradle.model.NoArg import org.jetbrains.kotlin.gradle.model.SAMWithReceiver initscript { dependencies { classpath(files(System.getProperty("org.jetbrains.kotlin.eclipse.gradle.model.path"))) } } allprojects { buildscript { dependencies { classpath(files(System.getProperty("org.jetbrains.kotlin.eclipse.gradle.model.path"))) } } apply() } class GradleProjectForEclipseInstaller @Inject constructor(val registry: ToolingModelBuilderRegistry) : Plugin { override fun apply(project: Project) { registry.register(GradleProjectForEclipseBuilder()) } } class GradleProjectForEclipseBuilder() : ToolingModelBuilder { override fun canBuild(modelName: String) = (modelName == GradleMultiProjectForEclipse::class.qualifiedName) override fun buildAll(modelName: String, project: Project): GradleMultiProjectForEclipse = GradleMultiProjectForEclipseImpl(process(project).toMap()) private fun process(project: Project): List> = project.childProjects.values.flatMap(::process) + (project.name to buildForSubproject(project)) private fun buildForSubproject(project: Project): GradleProjectForEclipse = project.tasks.findByName("compileKotlin") ?.dynamicCall("kotlinOptions") ?.run { KotlinGradleProject( project.findProperty("kotlin.code.style") as? String, property("apiVersion"), property("languageVersion"), property("jvmTarget"), collectPlugins(project) ) } ?: NonKotlinProject private fun collectPlugins(project: Project): List { val result = arrayListOf() project.extensions.findByName("allOpen")?.let { AllOpen( it.dynamicCall("myAnnotations") as List, it.dynamicCall("myPresets") as List ) }?.also { result += it } project.extensions.findByName("noArg")?.let { NoArg( it.dynamicCall("myAnnotations") as List, it.dynamicCall("myPresets") as List, it.dynamicCall("invokeInitializers") as Boolean ) }?.also { result += it } project.extensions.findByName("samWithReceiver")?.let { SAMWithReceiver( it.dynamicCall("myAnnotations") as List, it.dynamicCall("myPresets") as List ) }?.also { result += it } return result } // We need this method, because there is no way for us to get here classes that are added to classpath alongside // the kotlin gradle plugin. Even if we add them to the classpath of this initscript, they will have different // classloader. fun Any.dynamicCall(name: String, vararg args: Any?): Any? = this::class.members.first { it.name == name && it.parameters.size == args.size + 1 } .call(this, *args) fun Any.property(name: String): String? = dynamicCall(name) as? String } ================================================ FILE: kotlin-eclipse-gradle/src/org/jetbrains/kotlin/gradle/Activator.kt ================================================ package org.jetbrains.kotlin.gradle import org.osgi.framework.BundleActivator import org.osgi.framework.BundleContext class Activator: BundleActivator { override fun start(context: BundleContext?) { Activator.context = context } override fun stop(context: BundleContext?) { Activator.context = null } companion object { const val PLUGIN_ID = "org.jetbrains.kotlin.gradle" var context: BundleContext? = null private set } } ================================================ FILE: kotlin-eclipse-gradle/src/org/jetbrains/kotlin/gradle/configurator/KotlinProjectConfigurator.kt ================================================ package org.jetbrains.kotlin.gradle.configurator import org.eclipse.buildship.core.InitializationContext import org.eclipse.buildship.core.ProjectConfigurator import org.eclipse.buildship.core.ProjectContext import org.eclipse.core.resources.ProjectScope import org.eclipse.core.runtime.IProgressMonitor import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.config.LanguageVersion import org.jetbrains.kotlin.core.formatting.KotlinCodeStyleManager import org.jetbrains.kotlin.core.model.KotlinEnvironment import org.jetbrains.kotlin.core.model.KotlinNature import org.jetbrains.kotlin.core.preferences.KotlinCodeStyleProperties import org.jetbrains.kotlin.core.preferences.KotlinProperties import org.jetbrains.kotlin.core.utils.ProjectUtils import org.jetbrains.kotlin.gradle.model.GradleProjectForEclipse import org.jetbrains.kotlin.core.log.KotlinLogger import org.jetbrains.kotlin.gradle.model.GradleMultiProjectForEclipse class KotlinProjectConfigurator : ProjectConfigurator { lateinit var multiModel: GradleMultiProjectForEclipse override fun init(context: InitializationContext, monitor: IProgressMonitor) { context.gradleBuild.withConnection({ multiModel = it.getModel(GradleMultiProjectForEclipse::class.java) }, monitor) } override fun configure(context: ProjectContext, monitor: IProgressMonitor) { val project = context.project KotlinEnvironment.removeEnvironment(project) if (!::multiModel.isInitialized) return val model = multiModel[project.name] if (model == null || !model.isKotlinProject) { // Kotlin nature may left in .project file after editing out kotlin plugin from gradle buildfile. // This leads to nasty bugs so we have to unconfigure project. unconfigure(context, monitor) return } KotlinNature.addNature(project) if (!ProjectUtils.hasKotlinRuntime(project)) { ProjectUtils.addKotlinRuntime(project) } val compilerProperties = KotlinEnvironment.getEnvironment(project).projectCompilerProperties compilerProperties.loadDefaults() var configurationChanged = false fun String?.configure(action: KotlinProperties.(String) -> Unit) { this?.let { compilerProperties.action(it) configurationChanged = true } } model.jvmTarget.configure { jvmTarget = JvmTarget.fromString(it) ?: JvmTarget.DEFAULT } model.languageVersion.configure { languageVersion = LanguageVersion.fromVersionString(it) ?: LanguageVersion.LATEST_STABLE } model.apiVersion.configure { apiVersion = ApiVersion.parse(it) ?: ApiVersion.createByLanguageVersion(languageVersion) } configurationChanged = configurationChanged || model.compilerPlugins.any() model.compilerPlugins.forEach { compilerProperties.compilerPlugins[it.pluginName].apply { active = true args += it.options } } if (configurationChanged) { compilerProperties.globalsOverridden = true compilerProperties.saveChanges() } model.codestyle ?.let { KotlinCodeStyleManager.buildsystemAliases[it] } ?.also { with(KotlinCodeStyleProperties(ProjectScope(project))) { codeStyleId = it globalsOverridden = true saveChanges() } } } override fun unconfigure(context: ProjectContext, monitor: IProgressMonitor) { KotlinNature.removeNature(context.project) } } ================================================ FILE: kotlin-eclipse-gradle/src/org/jetbrains/kotlin/gradle/initialization/ModelInjector.kt ================================================ package org.jetbrains.kotlin.gradle.initialization import org.eclipse.buildship.core.invocation.InvocationCustomizer import org.eclipse.core.runtime.Platform import org.jetbrains.kotlin.gradle.Activator import org.eclipse.core.runtime.FileLocator import java.io.File import java.lang.management.ManagementFactory import org.jetbrains.kotlin.core.log.KotlinLogger class ModelInjector : InvocationCustomizer { override fun getExtraArguments() = listOf("--init-script", initializerPath) .also { System.setProperty(MODEL_PATH_PROPERTY, modelLibPath) } companion object { private const val MODEL_PATH_PROPERTY = "org.jetbrains.kotlin.eclipse.gradle.model.path" private val initializerPath by lazy { Platform.getBundle(Activator.PLUGIN_ID) .getEntry("scripts/init.gradle.kts") .let(FileLocator::toFileURL) .path } private val modelLibPath by lazy { Platform.getBundle("org.jetbrains.kotlin.gradle.model") .getEntry("lib/kotlin-eclipse-gradle-model.jar") .let(FileLocator::toFileURL) .path } } } ================================================ FILE: kotlin-eclipse-gradle-feature/build.properties ================================================ ############################################################################### # Copyright 2000-2014 JetBrains s.r.o. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### bin.includes = feature.xml ================================================ FILE: kotlin-eclipse-gradle-feature/feature.xml ================================================ Integration of Kotlin language plugin and gradle Copyright 2010-2016 JetBrains s.r.o. Copyright 2010-2016 JetBrains s.r.o. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. ================================================ FILE: kotlin-eclipse-gradle-feature/pom.xml ================================================ 4.0.0 ../pom.xml kotlin.eclipse kotlin.eclipse.plugin 0.8.24-SNAPSHOT org.jetbrains.kotlin.gradle.feature 0.8.24-SNAPSHOT eclipse-feature ================================================ FILE: kotlin-eclipse-gradle-model/META-INF/MANIFEST.MF ================================================ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: kotlin-eclipse-gradle-model Bundle-SymbolicName: org.jetbrains.kotlin.gradle.model;singleton:=true Bundle-Version: 0.8.24.qualifier Bundle-Vendor: JetBrains Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-ActivationPolicy: lazy Export-Package: org.jetbrains.kotlin.gradle.model Import-Package: kotlin ================================================ FILE: kotlin-eclipse-gradle-model/build.gradle ================================================ plugins { id 'org.jetbrains.kotlin.jvm' version '1.6.0' } group 'kotlin-eclipse-plugin' version '0.8.20-SNAPSHOT' repositories { mavenCentral() } dependencies { compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8" } sourceSets { main.kotlin.srcDirs += 'src' } compileKotlin { kotlinOptions.jvmTarget = "17" } compileTestKotlin { kotlinOptions.jvmTarget = "17" } jar { version = null destinationDir = file('lib') } ================================================ FILE: kotlin-eclipse-gradle-model/build.properties ================================================ source.. = src/ output.. = bin/ bin.includes = META-INF/,\ .,\ plugin.xml,\ scripts/,\ lib/ ================================================ FILE: kotlin-eclipse-gradle-model/gradle/wrapper/gradle-wrapper.properties ================================================ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-5.0-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists ================================================ FILE: kotlin-eclipse-gradle-model/gradlew ================================================ #!/usr/bin/env sh ############################################################################## ## ## Gradle start up script for UN*X ## ############################################################################## # Attempt to set APP_HOME # Resolve links: $0 may be a link PRG="$0" # Need this for relative symlinks. while [ -h "$PRG" ] ; do ls=`ls -ld "$PRG"` link=`expr "$ls" : '.*-> \(.*\)$'` if expr "$link" : '/.*' > /dev/null; then PRG="$link" else PRG=`dirname "$PRG"`"/$link" fi done SAVED="`pwd`" cd "`dirname \"$PRG\"`/" >/dev/null APP_HOME="`pwd -P`" cd "$SAVED" >/dev/null APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" warn () { echo "$*" } die () { echo echo "$*" echo exit 1 } # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false case "`uname`" in CYGWIN* ) cygwin=true ;; Darwin* ) darwin=true ;; MINGW* ) msys=true ;; NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables JAVACMD="$JAVA_HOME/jre/sh/java" else JAVACMD="$JAVA_HOME/bin/java" fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else JAVACMD="java" which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi # Increase the maximum file descriptors if we can. if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then MAX_FD_LIMIT=`ulimit -H -n` if [ $? -eq 0 ] ; then if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then MAX_FD="$MAX_FD_LIMIT" fi ulimit -n $MAX_FD if [ $? -ne 0 ] ; then warn "Could not set maximum file descriptor limit: $MAX_FD" fi else warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" fi fi # For Darwin, add options to specify how the application appears in the dock if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi # For Cygwin, switch paths to Windows format before running java if $cygwin ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` SEP="" for dir in $ROOTDIRSRAW ; do ROOTDIRS="$ROOTDIRS$SEP$dir" SEP="|" done OURCYGPATTERN="(^($ROOTDIRS))" # Add a user-defined pattern to the cygpath arguments if [ "$GRADLE_CYGPATTERN" != "" ] ; then OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" fi # Now convert the arguments - kludge to limit ourselves to /bin/sh i=0 for arg in "$@" ; do CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` else eval `echo args$i`="\"$arg\"" fi i=$((i+1)) done case $i in (0) set -- ;; (1) set -- "$args0" ;; (2) set -- "$args0" "$args1" ;; (3) set -- "$args0" "$args1" "$args2" ;; (4) set -- "$args0" "$args1" "$args2" "$args3" ;; (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi # Escape application args save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } APP_ARGS=$(save "$@") # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then cd "$(dirname "$0")" fi exec "$JAVACMD" "$@" ================================================ FILE: kotlin-eclipse-gradle-model/gradlew.bat ================================================ @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @rem @rem ########################################################################## @rem Set local scope for the variables with windows NT shell if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. set DEFAULT_JVM_OPTS="-Xmx64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if "%ERRORLEVEL%" == "0" goto init echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto init echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo. echo Please set the JAVA_HOME variable in your environment to match the echo location of your Java installation. goto fail :init @rem Get command-line arguments, handling Windows variants if not "%OS%" == "Windows_NT" goto win9xME_args :win9xME_args @rem Slurp the command line arguments. set CMD_LINE_ARGS= set _SKIP=2 :win9xME_args_slurp if "x%~1" == "x" goto execute set CMD_LINE_ARGS=%* :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% :end @rem End local scope for the variables with windows NT shell if "%ERRORLEVEL%"=="0" goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 exit /b 1 :mainEnd if "%OS%"=="Windows_NT" endlocal :omega ================================================ FILE: kotlin-eclipse-gradle-model/pom.xml ================================================ 4.0.0 ../pom.xml kotlin.eclipse kotlin.eclipse.plugin 0.8.24-SNAPSHOT org.jetbrains.kotlin.gradle.model eclipse-plugin src org.jetbrains.kotlin kotlin-maven-plugin ${kotlin.version} 17 compile process-sources compile ================================================ FILE: kotlin-eclipse-gradle-model/settings.gradle ================================================ pluginManagement { repositories { mavenCentral() maven { url 'https://plugins.gradle.org/m2/' } } } rootProject.name = 'kotlin-eclipse-gradle-model' ================================================ FILE: kotlin-eclipse-gradle-model/src/org/jetbrains/kotlin/gradle/model/GradleMultiProjectForEclipse.kt ================================================ package org.jetbrains.kotlin.gradle.model import java.io.Serializable interface GradleMultiProjectForEclipse : Serializable { operator fun get(name: String): GradleProjectForEclipse? } class GradleMultiProjectForEclipseImpl( private val subprojects: Map ) : GradleMultiProjectForEclipse { override fun get(name: String) = subprojects[name] } ================================================ FILE: kotlin-eclipse-gradle-model/src/org/jetbrains/kotlin/gradle/model/GradleProjectForEclipse.kt ================================================ package org.jetbrains.kotlin.gradle.model import java.io.Serializable // This interface is used to communicate with gradle deamon via proxy, so it has to have all methods that are expected // in its subclasses. interface GradleProjectForEclipse : Serializable { val isKotlinProject: Boolean val codestyle: String? get() = null val apiVersion: String? get() = null val languageVersion: String? get() = null val jvmTarget: String? get() = null val compilerPlugins: List get() = emptyList() } data class KotlinGradleProject( override val codestyle: String?, override val apiVersion: String?, override val languageVersion: String?, override val jvmTarget: String?, override val compilerPlugins: List ) : GradleProjectForEclipse { override val isKotlinProject: Boolean = true } object NonKotlinProject : GradleProjectForEclipse { override val isKotlinProject: Boolean = false } ================================================ FILE: kotlin-eclipse-gradle-model/src/org/jetbrains/kotlin/gradle/model/plugins.kt ================================================ package org.jetbrains.kotlin.gradle.model import java.io.Serializable interface CompilerPluginConfig: Serializable { val pluginName: String val options: List } sealed class CompilerPluginConfigImpl( shortName: String, fqName: String, knownPresets: Collection, declaredAnnotations: Collection, declaredPresets: Collection, otherOptions: List = emptyList() ) : CompilerPluginConfig { final override val pluginName: String = knownPresets.find { it in declaredPresets } ?: shortName override val options: List = (declaredPresets - pluginName).map { "$fqName:preset=$it" } + declaredAnnotations.map { "$fqName:annotation=$it" } + otherOptions } class AllOpen( annotations: Collection, presets: Collection ) : CompilerPluginConfigImpl( shortName = "all-open", fqName = "org.jetbrains.kotlin.allopen", knownPresets = listOf("spring"), declaredAnnotations = annotations, declaredPresets = presets ) class NoArg( annotations: Collection, presets: Collection, invokeInitializers: Boolean? ) : CompilerPluginConfigImpl( shortName = "no-arg", fqName = "org.jetbrains.kotlin.noarg", knownPresets = listOf("jpa"), declaredAnnotations = annotations, declaredPresets = presets, otherOptions = invokeInitializers?.let { listOf("org.jetbrains.kotlin.noarg:invokeInitializers=$it") }.orEmpty() ) class SAMWithReceiver( annotations: Collection, presets: Collection ) : CompilerPluginConfigImpl( shortName = "sam-with-receiver", fqName = "org.jetbrains.kotlin.samWithReceiver", knownPresets = emptyList(), declaredAnnotations = annotations, declaredPresets = presets ) ================================================ FILE: kotlin-eclipse-maven/META-INF/MANIFEST.MF ================================================ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: kotlin-eclipse-maven Bundle-SymbolicName: org.jetbrains.kotlin.maven;singleton:=true Bundle-Version: 0.8.24.qualifier Bundle-Activator: org.jetbrains.kotlin.maven.Activator Bundle-Vendor: JetBrains Require-Bundle: org.eclipse.core.runtime, org.eclipse.m2e.core, org.eclipse.m2e.jdt, org.eclipse.m2e.maven.runtime, org.jetbrains.kotlin.core, org.jetbrains.kotlin.bundled-compiler Bundle-RequiredExecutionEnvironment: JavaSE-17 Bundle-ActivationPolicy: lazy Import-Package: org.eclipse.core.resources, org.eclipse.jdt.core, org.eclipse.m2e.core.project.configurator ================================================ FILE: kotlin-eclipse-maven/build.properties ================================================ source.. = src/ output.. = bin/ bin.includes = META-INF/,\ .,\ plugin.xml,\ lifecycle-mapping-metadata.xml ================================================ FILE: kotlin-eclipse-maven/lifecycle-mapping-metadata.xml ================================================ org.jetbrains.kotlin kotlin-maven-plugin [0.0,) compile test-compile org.jetbrains.kotlin.maven.projectConfigurator ================================================ FILE: kotlin-eclipse-maven/plugin.xml ================================================ ================================================ FILE: kotlin-eclipse-maven/pom.xml ================================================ 4.0.0 ../pom.xml kotlin.eclipse kotlin.eclipse.plugin 0.8.24-SNAPSHOT org.jetbrains.kotlin.maven eclipse-plugin src org.jetbrains.kotlin kotlin-maven-plugin ${kotlin.version} 17 compile process-sources compile ================================================ FILE: kotlin-eclipse-maven/src/org/jetbrains/kotlin/maven/Activator.java ================================================ package org.jetbrains.kotlin.maven; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; public class Activator implements BundleActivator { private static BundleContext context; static BundleContext getContext() { return context; } /* * (non-Javadoc) * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) */ public void start(BundleContext bundleContext) throws Exception { Activator.context = bundleContext; } /* * (non-Javadoc) * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) */ public void stop(BundleContext bundleContext) throws Exception { Activator.context = null; } } ================================================ FILE: kotlin-eclipse-maven/src/org/jetbrains/kotlin/maven/configuration/KotlinMavenProjectConfigurator.kt ================================================ package org.jetbrains.kotlin.maven.configuration import org.apache.maven.model.Plugin import org.apache.maven.project.MavenProject import org.codehaus.plexus.util.xml.Xpp3Dom import org.eclipse.core.resources.ProjectScope import org.eclipse.core.runtime.IProgressMonitor import org.eclipse.m2e.core.project.configurator.AbstractProjectConfigurator import org.eclipse.m2e.core.project.configurator.ProjectConfigurationRequest import org.eclipse.m2e.jdt.AbstractSourcesGenerationProjectConfigurator import org.eclipse.m2e.jdt.IClasspathDescriptor import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.config.LanguageVersion import org.jetbrains.kotlin.core.KotlinClasspathContainer import org.jetbrains.kotlin.core.formatting.KotlinCodeStyleManager import org.jetbrains.kotlin.core.model.KotlinEnvironment import org.jetbrains.kotlin.core.model.KotlinNature import org.jetbrains.kotlin.core.preferences.KotlinCodeStyleProperties private const val GROUP_ID = "org.jetbrains.kotlin" private const val MAVEN_PLUGIN_ID = "kotlin-maven-plugin" class KotlinMavenProjectConfigurator : AbstractSourcesGenerationProjectConfigurator() { override fun configure(request: ProjectConfigurationRequest, monitor: IProgressMonitor) { val mavenProject = request.mavenProject val plugin: Plugin = mavenProject.buildPlugins .find { checkCoordinates(it, GROUP_ID, MAVEN_PLUGIN_ID) } ?: return val compilerProperties = KotlinEnvironment.getEnvironment(request.mavenProjectFacade.project).projectCompilerProperties var configurationChanged = false fun configureProperty( attributeName: String? = null, propertyPath: String? = null, isChangingConfiguration: Boolean = true, callback: (String) -> Unit ) { MavenAttributeAccessor(attributeName, propertyPath) .getFrom(mavenProject, plugin) ?.also(callback) ?.also { configurationChanged = configurationChanged || isChangingConfiguration } } configureProperty("languageVersion", "kotlin.compiler.languageVersion") { compilerProperties.languageVersion = LanguageVersion.fromVersionString(it) ?: LanguageVersion.LATEST_STABLE } configureProperty("apiVersion", "kotlin.compiler.apiVersion") { compilerProperties.apiVersion = ApiVersion.parse(it) ?: ApiVersion.createByLanguageVersion(compilerProperties.languageVersion) } configureProperty("jvmTarget", "kotlin.compiler.jvmTarget") { compilerProperties.jvmTarget = JvmTarget.fromString(it) ?: JvmTarget.DEFAULT } getCompilerFlags(plugin.configuration)?.also { compilerProperties.compilerFlags = it configurationChanged = true } configureProperty(propertyPath = "kotlin.code.style", isChangingConfiguration = false) { alias -> KotlinCodeStyleManager.buildsystemAliases[alias]?.let { with(KotlinCodeStyleProperties(ProjectScope(request.mavenProjectFacade.project))) { codeStyleId = it globalsOverridden = true saveChanges() } } } if (configurationChanged) { compilerProperties.globalsOverridden = true compilerProperties.saveChanges() } } override fun configureRawClasspath( request: ProjectConfigurationRequest, classpath: IClasspathDescriptor, monitor: IProgressMonitor ) { if (hasKotlinMavenPlugin(request.mavenProject)) { classpath.addEntry(KotlinClasspathContainer.CONTAINER_ENTRY) AbstractProjectConfigurator.addNature(request.mavenProjectFacade.project, KotlinNature.KOTLIN_NATURE, monitor) } } private fun getCompilerFlags(configuration: Any?): String? = (configuration as? Xpp3Dom) ?.getChild("args") ?.children ?.filter { it.name == "arg" } ?.map { it.value } ?.takeIf { it.isNotEmpty() } ?.joinToString(separator = " ") private fun hasKotlinMavenPlugin(mavenProject: MavenProject): Boolean = mavenProject.buildPlugins.any { checkCoordinates(it, GROUP_ID, MAVEN_PLUGIN_ID) } private fun checkCoordinates(buildPlugin: Plugin, groupId: String, artifactId: String): Boolean = groupId == buildPlugin.groupId && artifactId == buildPlugin.artifactId } ================================================ FILE: kotlin-eclipse-maven/src/org/jetbrains/kotlin/maven/configuration/MavenAttributeAccessor.kt ================================================ package org.jetbrains.kotlin.maven.configuration import org.apache.maven.model.Plugin import org.apache.maven.project.MavenProject import org.codehaus.plexus.util.xml.Xpp3Dom import java.util.* class MavenAttributeAccessor(private val attributeName: String? = null, private val propertyPath: String? = null) { fun getFrom(project: MavenProject, plugin: Plugin): String? = getFromConfiguration(plugin.configuration) ?: getFromProperties(project.properties) private fun getFromConfiguration(configuration: Any?): String? = (configuration as? Xpp3Dom) ?.getChild(attributeName) ?.value private fun getFromProperties(properties: Properties): String? = propertyPath?.let { properties[it] as? String } } ================================================ FILE: kotlin-eclipse-p2updatesite/category.xml ================================================ ================================================ FILE: kotlin-eclipse-p2updatesite/pom.xml ================================================ 4.0.0 ../pom.xml kotlin.eclipse kotlin.eclipse.plugin 0.8.24-SNAPSHOT org.jetbrains.kotlin.p2updatesite 0.8.24-SNAPSHOT eclipse-repository ================================================ FILE: kotlin-eclipse-policy/build.properties ================================================ bin.includes = feature.xml ================================================ FILE: kotlin-eclipse-policy/feature.xml ================================================ Copyright 2010-2016 JetBrains s.r.o. JetBrains Privacy Policy This software is governed by JetBrains Privacy Policy. https://www.jetbrains.com/company/privacy.html ================================================ FILE: kotlin-eclipse-policy/pom.xml ================================================ 4.0.0 ../pom.xml kotlin.eclipse kotlin.eclipse.plugin 0.8.24-SNAPSHOT org.jetbrains.kotlin.policy 0.8.24-SNAPSHOT eclipse-feature ================================================ FILE: kotlin-eclipse-test-framework/META-INF/MANIFEST.MF ================================================ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: kotlin-eclipse-testframework Bundle-SymbolicName: org.jetbrains.kotlin.testframework Bundle-Version: 0.8.24.qualifier Bundle-Activator: org.jetbrains.kotlin.testframework.Activator Require-Bundle: org.jetbrains.kotlin.core, org.jetbrains.kotlin.ui, org.eclipse.ui, org.eclipse.core.runtime, org.eclipse.ui.editors;bundle-version="3.8.0", org.eclipse.jface.text;bundle-version="3.8.1", org.jetbrains.kotlin.bundled-compiler, org.eclipse.jdt.ui Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-17 Import-Package: junit.framework;version="4.10.0", org.eclipse.core.resources, org.eclipse.jdt.core, org.eclipse.jdt.launching, org.eclipse.jface.text, org.eclipse.ui.part, org.junit;version="4.10.0", org.junit.rules;version="4.10.0" Export-Package: org.jetbrains.kotlin.testframework.editor, org.jetbrains.kotlin.testframework.utils Bundle-Vendor: JetBrains ================================================ FILE: kotlin-eclipse-test-framework/build.properties ================================================ ############################################################################### # Copyright 2000-2014 JetBrains s.r.o. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### source.. = src/ output.. = bin/ bin.includes = META-INF/,\ . ================================================ FILE: kotlin-eclipse-test-framework/pom.xml ================================================ 4.0.0 ../pom.xml kotlin.eclipse kotlin.eclipse.plugin 0.8.24-SNAPSHOT org.jetbrains.kotlin.testframework eclipse-plugin src org.jetbrains.kotlin kotlin-maven-plugin ${kotlin.version} 17 compile process-sources compile org.apache.maven.plugins maven-compiler-plugin 3.10.1 17 ================================================ FILE: kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/Activator.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.testframework; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.osgi.framework.BundleContext; /** * The activator class controls the plug-in life cycle */ public class Activator extends AbstractUIPlugin { // The plug-in ID public static final String PLUGIN_ID = "org.jetbrains.kotlin.testframework"; //$NON-NLS-1$ // The shared instance private static Activator plugin; /** * The constructor */ public Activator() { } /* * (non-Javadoc) * * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework. * BundleContext) */ @Override public void start(BundleContext context) throws Exception { super.start(context); plugin = this; } /* * (non-Javadoc) * * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework. * BundleContext) */ @Override public void stop(BundleContext context) throws Exception { plugin = null; super.stop(context); } /** * Returns the shared instance * * @return the shared instance */ public static Activator getDefault() { return plugin; } } ================================================ FILE: kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/editor/KotlinEditorAutoTestCase.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.testframework.editor; import java.io.File; import org.jetbrains.kotlin.testframework.utils.KotlinTestUtils; import org.jetbrains.kotlin.testframework.utils.SourceFileData; import org.junit.Rule; import org.junit.rules.TestName; public abstract class KotlinEditorAutoTestCase extends KotlinProjectTestCase { protected abstract static class EditorSourceFileData extends SourceFileData { public EditorSourceFileData(File file) { super(file.getName(), KotlinTestUtils.getText(file.getAbsolutePath())); } } @Rule public TestName name = new TestName(); private static final String TEST_DATA_PATH = "testData"; private static String fileExtension; private static final String KT_FILE_EXTENSION = ".kt"; private static final String KT_SCRIPT_FILE_EXTENSION = ".kts"; protected static final String AFTER_FILE_EXTENSION = ".after"; protected static final String BEFORE_FILE_EXTENSION = ".before"; protected static final String FILE_DEPENDENCY_SUFFIX = ".dependency"; protected final void doAutoTest() { String testPath = TEST_DATA_PATH + "/" + getTestDataRelativePath() + "/" + name.getMethodName(); File testFolder = new File(testPath); File testFile = new File(testPath + KT_FILE_EXTENSION); File scriptTestFile = new File(testPath + KT_SCRIPT_FILE_EXTENSION); if (testFile.exists()) { fileExtension = KT_FILE_EXTENSION; } else { testFile = scriptTestFile; fileExtension = KT_SCRIPT_FILE_EXTENSION; } File dependencyFile = new File(testPath + FILE_DEPENDENCY_SUFFIX + getExtension()); if (testFolder.exists() && testFolder.isDirectory()) { doMultiFileAutoTest(testFolder); } else if (testFile.exists() && testFile.isFile() && dependencyFile.exists()) { doAutoTestWithDependencyFile(testPath + getExtension(), dependencyFile); } else if (testFile.exists() && testFile.isFile() && !dependencyFile.exists()) { doSingleFileAutoTest(testPath + getExtension()); } else { throw new RuntimeException(String.format("Neither file \'%s\' nor directory \'%s\' was found", testFile.getAbsolutePath(), testFolder.getAbsolutePath())); } } protected abstract void doSingleFileAutoTest(String testPath); protected abstract void doMultiFileAutoTest(File testFolder); protected void doAutoTestWithDependencyFile(String mainTestPath, File dependencyFile) { throw new UnsupportedOperationException("Auto test with dependency file is not supported"); } protected abstract String getTestDataRelativePath(); protected String getExtension() { return fileExtension; } } ================================================ FILE: kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/editor/KotlinEditorSequentialAutoTestCase.java ================================================ package org.jetbrains.kotlin.testframework.editor; import java.io.File; import java.util.ArrayList; import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor; import org.eclipse.ui.PlatformUI; import org.jetbrains.kotlin.testframework.utils.EditorTestUtils; import org.jetbrains.kotlin.testframework.utils.KotlinTestUtils; public abstract class KotlinEditorSequentialAutoTestCase extends KotlinEditorAutoTestCase { @Override protected void doSingleFileAutoTest(String testPath) { throw new UnsupportedOperationException("Single-file tests are not supported for this case"); } abstract protected void performSingleOperation(); abstract protected String getInitialFileName(); private TextEditorTest testEditor; protected TextEditorTest getTestEditor() { return testEditor; } @Override protected void doMultiFileAutoTest(File testFolder) { testEditor = configureEditor(getInitialFileName(), getInitialFileContent(testFolder)); ArrayList afterFilesPaths = getAfterFilesPaths(testFolder); JavaEditor activeEditor = (JavaEditor) PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor(); for (String afterFilePath : afterFilesPaths) { String afterFileContent = getAfterFileContent(afterFilePath); performSingleOperation(); String errorMessage = String.format("Comparison error: %s", afterFilePath); EditorTestUtils.assertByEditorWithErrorMessage(activeEditor, afterFileContent, errorMessage); } } protected String getInitialFileContent(File testFolder) { return KotlinTestUtils.getText(testFolder.getAbsolutePath() + File.separator + getInitialFileName()); } abstract protected ArrayList getAfterFilesPaths(File testFolder); abstract protected String getAfterFileContent(String afterFilePath); } ================================================ FILE: kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/editor/KotlinEditorTestCase.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.testframework.editor; import java.io.File; import java.io.IOException; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.editors.text.EditorsUI; import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants; import org.jetbrains.kotlin.testframework.utils.TestJavaProject; import org.jetbrains.kotlin.testframework.utils.WorkspaceUtil; import org.jetbrains.kotlin.ui.editors.KotlinFileEditor; import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.rules.TestName; import com.intellij.openapi.util.io.FileUtil; public abstract class KotlinEditorTestCase { public enum Separator { TAB, SPACE; } public static final String CARET_TAG = ""; public static final String SELECTION_TAG_OPEN = ""; public static final String SELECTION_TAG_CLOSE = ""; public static final String ERROR_TAG_OPEN = ""; public static final String ERROR_TAG_CLOSE = ""; public static final String WARNING_TAG_OPEN = ""; public static final String WARNING_TAG_CLOSE = ""; public static final String BREAK_TAG = "
"; public static final String REFERENCE_TAG = ""; @Rule public TestName name = new TestName(); protected TextEditorTest testEditor; private Separator initialSeparator; private int initialSpacesCount; @After public void afterTest() { deleteProjectAndCloseEditors(); EditorsUI.getPreferenceStore().setValue(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SPACES_FOR_TABS, (Separator.SPACE == initialSeparator)); EditorsUI.getPreferenceStore().setValue(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH, initialSpacesCount); } @Before public void beforeTest() { refreshWorkspace(); initialSeparator = EditorsUI.getPreferenceStore().getBoolean( AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SPACES_FOR_TABS) ? Separator.SPACE : Separator.TAB; initialSpacesCount = EditorsUI.getPreferenceStore().getInt( AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH); } protected KotlinFileEditor getEditor() { return (KotlinFileEditor) testEditor.getEditor(); } protected int getCaret() { return getEditor().getViewer().getTextWidget().getCaretOffset(); } public IFile createSourceFile(String pkg, String fileName, String content) { content = removeTags(content); try { if (testEditor == null) { testEditor = new TextEditorTest(TextEditorTest.TEST_PROJECT_NAME); } return testEditor.getTestJavaProject().createSourceFile(pkg, fileName, content); } catch (CoreException e) { throw new RuntimeException(e); } } public IFile createSourceFile(String fileName, String content) { return createSourceFile(TextEditorTest.TEST_PACKAGE_NAME, fileName, content); } protected static TextEditorTest configureEditor(String fileName, String content) { return configureEditor(fileName, content, TextEditorTest.TEST_PACKAGE_NAME); } protected static TextEditorTest configureEditor(String fileName, String content, String packageName) { return configureEditor(fileName, content, TextEditorTest.TEST_PROJECT_NAME, packageName); } protected static TextEditorTest configureEditor(String fileName, String content, String projectName, String packageName) { TextEditorTest testEditor = new TextEditorTest(projectName); testEditor.createEditor(fileName, resolveTestTags(content), packageName); return testEditor; } private void deleteProjectAndCloseEditors() { try { joinBuildThread(); PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().closeAllEditors(false); if (testEditor != null) { TestJavaProject testJavaProject = testEditor.getTestJavaProject(); if (testJavaProject != null) { testJavaProject.clean(); } } IProject projects[] = ResourcesPlugin.getWorkspace().getRoot().getProjects(); for (IProject project : projects) { project.delete(true, true, null); } } catch (CoreException e) { e.printStackTrace(); } } public static void refreshWorkspace() { WorkspaceUtil.refreshWorkspace(); try { Job.getJobManager().join(ResourcesPlugin.FAMILY_MANUAL_REFRESH, new NullProgressMonitor()); } catch (OperationCanceledException | InterruptedException e) { e.printStackTrace(); } } public static String getText(String testPath) { return getText(new File(testPath)); } public static String getText(File file) { try { return String.valueOf(FileUtil.loadFile(file)); } catch (IOException e) { throw new RuntimeException(e); } } public static void joinBuildThread() { while (true) { try { Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_BUILD, null); break; } catch (OperationCanceledException | InterruptedException e) { } } } public static String resolveTestTags(String text) { return text .replaceAll(ERROR_TAG_OPEN, "") .replaceAll(ERROR_TAG_CLOSE, "") .replaceAll(WARNING_TAG_OPEN, "") .replaceAll(WARNING_TAG_CLOSE, "") .replaceAll(BREAK_TAG, System.lineSeparator()); } public static String removeTags(String text) { return resolveTestTags(text) .replaceAll(CARET_TAG, "") .replaceAll(SELECTION_TAG_OPEN, "") .replaceAll(SELECTION_TAG_CLOSE, "") .replaceAll(REFERENCE_TAG, ""); } public static String getNameByPath(String testPath) { return new Path(testPath).lastSegment(); } } ================================================ FILE: kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/editor/KotlinEditorWithAfterFileTestCase.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.testframework.editor; import com.intellij.openapi.util.Condition; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.kotlin.testframework.utils.KotlinTestUtils; import org.jetbrains.kotlin.testframework.utils.SourceFileData; import java.io.File; import java.io.IOException; import java.util.Collection; import java.util.HashMap; import java.util.Map; public abstract class KotlinEditorWithAfterFileTestCase extends KotlinEditorAutoTestCase { public enum AfterSuffixPosition { BEFORE_DOT, AFTER_NAME } protected AfterSuffixPosition getAfterPosition() { return AfterSuffixPosition.AFTER_NAME; } private static class WithAfterSourceFileData extends EditorSourceFileData { private static final Condition TARGET_PREDICATE = new Condition() { @Override public boolean value(WithAfterSourceFileData data) { return data.contentAfter != null; } }; private static final String NO_TARGET_FILE_FOUND_ERROR_MESSAGE = "No target file found"; private static final String NO_TARGET_FILE_FOUND_FOR_AFTER_FILE_ERROR_MESSAGE_FORMAT = "No target file found for \'%s\' file"; private String contentAfter = null; public WithAfterSourceFileData(File file) { super(file); } public String getContentAfter() { return contentAfter; } public static Collection getTestFiles(File testFolder) { Map result = new HashMap(); File targetAfterFile = null; for (File file : testFolder.listFiles()) { String fileName = file.getName(); if (!fileName.endsWith(AFTER_FILE_EXTENSION)) { result.put(fileName, new WithAfterSourceFileData(file)); } else { targetAfterFile = file; } } if (targetAfterFile == null) { throw new RuntimeException(NO_TARGET_FILE_FOUND_ERROR_MESSAGE); } WithAfterSourceFileData target = result.get(targetAfterFile.getName().replace(AFTER_FILE_EXTENSION, "")); if (target == null) { throw new RuntimeException(String.format(NO_TARGET_FILE_FOUND_FOR_AFTER_FILE_ERROR_MESSAGE_FORMAT, targetAfterFile.getAbsolutePath())); } target.contentAfter = KotlinTestUtils.getText(targetAfterFile.getAbsolutePath()); return result.values(); } public static WithAfterSourceFileData getTargetFile(Iterable files) { return ContainerUtil.find(files, TARGET_PREDICATE); } } private TextEditorTest testEditor; protected abstract void performTest(String fileText, String expectedFileText); protected TextEditorTest getTestEditor() { return testEditor; } protected boolean loadFilesBeforeOpeningEditor() { return false; } @Override protected void doSingleFileAutoTest(String testPath) { String fileText = loadEditor(testPath); String afterTestPath; AfterSuffixPosition afterPosition = getAfterPosition(); if (afterPosition == AfterSuffixPosition.AFTER_NAME) { afterTestPath = testPath + AFTER_FILE_EXTENSION; } else { afterTestPath = testPath.substring(0, testPath.length() - getExtension().length()) + AFTER_FILE_EXTENSION + getExtension(); } performTest(fileText, KotlinTestUtils.getText(afterTestPath)); } @Override protected void doMultiFileAutoTest(File testFolder) { Collection files = WithAfterSourceFileData.getTestFiles(testFolder); WithAfterSourceFileData target = WithAfterSourceFileData.getTargetFile(files); if (loadFilesBeforeOpeningEditor()) { loadFiles(files, target); testEditor = configureEditor(target.getFileName(), target.getContent(), target.getPackageName()); } else { testEditor = configureEditor(target.getFileName(), target.getContent(), target.getPackageName()); loadFiles(files, target); } performTest(target.getContent(), target.getContentAfter()); } private void loadFiles(Collection files, WithAfterSourceFileData target) { for (WithAfterSourceFileData file : files) { if (file != target) { createSourceFile(file.getPackageName(), file.getFileName(), file.getContent()); } } } @Override protected void doAutoTestWithDependencyFile(String mainTestPath, File dependencyFile) { String fileText; if (loadFilesBeforeOpeningEditor()) { loadDependencyFile(dependencyFile); fileText = loadEditor(mainTestPath); } else { fileText = loadEditor(mainTestPath); loadDependencyFile(dependencyFile); } performTest(fileText, KotlinTestUtils.getText(mainTestPath + AFTER_FILE_EXTENSION)); } private String loadEditor(String mainTestPath) { String fileText = KotlinTestUtils.getText(mainTestPath); testEditor = configureEditor(KotlinTestUtils.getNameByPath(mainTestPath), fileText, WithAfterSourceFileData.getPackageFromContent(fileText)); return fileText; } private void loadDependencyFile(File dependencyFile) { try { SourceFileData dependencySourceFile = new SourceFileData(dependencyFile); String fileName = dependencySourceFile.getFileName(); String dependencyFileName = fileName.substring(0, fileName.indexOf(FILE_DEPENDENCY_SUFFIX)) + "_dependency" + getExtension(); createSourceFile(dependencySourceFile.getPackageName(), dependencyFileName, dependencySourceFile.getContent()); } catch (IOException e) { throw new RuntimeException(e); } } } ================================================ FILE: kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/editor/KotlinProjectTestCase.java ================================================ package org.jetbrains.kotlin.testframework.editor; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.editors.text.EditorsUI; import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants; import org.jetbrains.kotlin.testframework.editor.KotlinEditorTestCase.Separator; import org.jetbrains.kotlin.testframework.utils.KotlinTestUtils; import org.jetbrains.kotlin.testframework.utils.TestJavaProject; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; public class KotlinProjectTestCase { private static TestJavaProject testJavaProject; private int initialSpacesCount; private Separator initialSeparator; @Before public void beforeTest() { KotlinTestUtils.refreshWorkspace(); initialSeparator = EditorsUI.getPreferenceStore().getBoolean(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SPACES_FOR_TABS) ? Separator.SPACE : Separator.TAB; initialSpacesCount = EditorsUI.getPreferenceStore().getInt(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH); EditorsUI.getPreferenceStore().setValue(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SPACES_FOR_TABS, true); EditorsUI.getPreferenceStore().setValue(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH, 4); } @After public void afterTest() { PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().closeAllEditors(false); if (testJavaProject != null) { testJavaProject.clean(); } EditorsUI.getPreferenceStore().setValue(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SPACES_FOR_TABS, (Separator.SPACE == initialSeparator)); EditorsUI.getPreferenceStore().setValue(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH, initialSpacesCount); } @AfterClass public static void afterAllTests() { if (testJavaProject != null) { testJavaProject.clean(); testJavaProject.setDefaultSettings(); } try { IProject projects[] = ResourcesPlugin.getWorkspace().getRoot().getProjects(); for (IProject project : projects) { project.delete(true, true, null); } } catch (CoreException e) { throw new RuntimeException(e); } } protected void configureProject() { configureProject(TextEditorTest.TEST_PROJECT_NAME); } protected void configureProject(String projectName) { configureProject(projectName, null); } protected void configureProject(String projectName, String location) { testJavaProject = new TestJavaProject(projectName, location); } protected void configureProjectWithStdLib() { configureProjectWithStdLib(TextEditorTest.TEST_PROJECT_NAME); } protected void configureProjectWithStdLib(String projectName) { configureProjectWithStdLib(projectName, null); } protected void configureProjectWithStdLib(String projectName, String location) { configureProject(projectName, location); try { testJavaProject.addKotlinRuntime(); } catch (CoreException e) { throw new RuntimeException(e); } } public IFile createSourceFile(String pkg, String fileName, String content) { try { return testJavaProject.createSourceFile(pkg, fileName, KotlinEditorTestCase.removeTags(content)); } catch (CoreException e) { throw new RuntimeException(e); } } public IFile createSourceFile(String fileName, String content) { return createSourceFile("", fileName, content); } protected TextEditorTest configureEditor(String fileName, String content) { return configureEditor(fileName, content, ""); } protected TextEditorTest configureEditor(String fileName, String content, String pkg) { TextEditorTest testEditor = new TextEditorTest(testJavaProject); testEditor.createEditor(fileName, content, pkg); return testEditor; } protected TestJavaProject getTestProject() { return testJavaProject; } protected void waitForEditorInitialization(TextEditorTest testEditor) { // TODO } } ================================================ FILE: kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/editor/TextEditorTest.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.testframework.editor; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.ITextSelection; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Event; import org.jetbrains.kotlin.eclipse.ui.utils.EditorUtil; import org.jetbrains.kotlin.testframework.utils.EditorTestUtils; import org.jetbrains.kotlin.testframework.utils.TestJavaProject; import org.jetbrains.kotlin.ui.editors.KotlinEditor; import org.jetbrains.kotlin.ui.editors.KotlinFormatAction; import org.jetbrains.kotlin.ui.editors.navigation.KotlinOpenDeclarationAction; import org.jetbrains.kotlin.ui.editors.selection.KotlinSelectEnclosingAction; import org.jetbrains.kotlin.ui.editors.selection.KotlinSelectNextAction; import org.jetbrains.kotlin.ui.editors.selection.KotlinSelectPreviousAction; public class TextEditorTest { public static final String TEST_PROJECT_NAME = "test_project"; public static final String TEST_PACKAGE_NAME = "testing"; private TestJavaProject testProject; private JavaEditor editor = null; public TextEditorTest() { this(TEST_PROJECT_NAME); } public TextEditorTest(String projectName) { testProject = new TestJavaProject(projectName); } public TextEditorTest(TestJavaProject testProject) { this.testProject = testProject; } public TestJavaProject getTestJavaProject() { return testProject; } public IProject getEclipseProject() { return testProject.getJavaProject().getProject(); } public JavaEditor createEditor(String name, String content) { return createEditor(name, content, TEST_PACKAGE_NAME); } public JavaEditor createEditor(String name, String content, String packageName) { if (editor == null) { try { int cursor = content.indexOf(KotlinEditorTestCase.CARET_TAG); content = content.replaceAll(KotlinEditorTestCase.CARET_TAG, ""); int selectionStart = content.indexOf(KotlinEditorTestCase.SELECTION_TAG_OPEN); content = content.replaceAll(KotlinEditorTestCase.SELECTION_TAG_OPEN, ""); int selectionEnd = content.indexOf(KotlinEditorTestCase.SELECTION_TAG_CLOSE); content = content.replaceAll(KotlinEditorTestCase.SELECTION_TAG_CLOSE, ""); IFile file = testProject.createSourceFile(packageName, name, content); editor = (JavaEditor) EditorTestUtils.openInEditor(file); setCaret(cursor); setSelection(selectionStart, selectionEnd - selectionStart); } catch (Exception e) { throw new RuntimeException(e); } } return editor; } public void type(char c) { Event e = new Event(); e.character = c; e.widget = editor.getViewer().getTextWidget(); e.widget.notifyListeners(SWT.KeyDown, e); } public void runOpenDeclarationAction() { ((KotlinEditor) editor).getJavaEditor().getAction(KotlinOpenDeclarationAction.OPEN_EDITOR_TEXT).run(); } public void runFormatAction() { ((KotlinEditor) editor).getJavaEditor().getAction(KotlinFormatAction.Companion.getFORMAT_ACTION_TEXT()).run(); } public void runSelectEnclosingAction() { ((KotlinEditor) editor).getJavaEditor().getAction(KotlinSelectEnclosingAction.SELECT_ENCLOSING_TEXT).run(); } public void runSelectPreviousAction() { ((KotlinEditor) editor).getJavaEditor().getAction(KotlinSelectPreviousAction.SELECT_PREVIOUS_TEXT).run(); } public void runSelectNextAction() { ((KotlinEditor) editor).getJavaEditor().getAction(KotlinSelectNextAction.SELECT_NEXT_TEXT).run(); } public int getCaretOffset() { return ((ITextSelection) editor.getViewer().getSelectionProvider().getSelection()).getOffset(); } public void setCaret(int offset) { if (offset > -1) { editor.setHighlightRange(offset, 0, true); editor.setFocus(); } } public void setSelection(int selectionStart, int selectionLength) { if (selectionStart >= 0 && selectionLength >= 0) { editor.selectAndReveal(selectionStart, selectionLength); } } public void typeEnter() { type('\n'); } public void save() { editor.doSave(null); } public void close() { editor.close(false); } public IFile getEditingFile() { return EditorUtil.getFile(editor); } public String getEditorInput() { return EditorUtil.getDocument(editor).get(); } public void deleteEditingFile() { IFile editingFile = getEditingFile(); close(); try { editingFile.delete(true, null); } catch (CoreException e) { throw new RuntimeException(e); } } public JavaEditor getEditor() { return editor; } public IDocument getDocument() { return editor.getDocumentProvider().getDocument(editor.getEditorInput()); } } ================================================ FILE: kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/utils/CodeStyleConfigurator.kt ================================================ package org.jetbrains.kotlin.testframework.utils import org.eclipse.core.resources.IProject import org.eclipse.core.resources.ProjectScope import org.jetbrains.kotlin.core.formatting.KotlinCodeStyleManager import org.jetbrains.kotlin.core.preferences.KotlinCodeStyleProperties import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.idea.core.formatter.KotlinCodeStyleSettings import java.util.* import kotlin.reflect.KFunction import kotlin.reflect.KMutableProperty object CodeStyleConfigurator { fun configure(project: IProject, fileText: String) { val generatedId = UUID.randomUUID().toString() KotlinCodeStyleProperties(ProjectScope(project)).apply { codeStyleId = generatedId globalsOverridden = true saveChanges() } KotlinCodeStyleManager.getOrCreate(generatedId) { val kotlinSettings = getCustomSettings(KotlinCodeStyleSettings::class.java) val commonSettings = getCommonSettings(KotlinLanguage.INSTANCE) fun setDynamic(prop: String, value: Any) { kotlinSettings.setDynamic(prop, value) or commonSettings.setDynamic(prop, value) } InTextDirectivesUtils.findListWithPrefixes(fileText, "SET_TRUE:") .forEach { setDynamic(it, true) } InTextDirectivesUtils.findListWithPrefixes(fileText, "SET_FALSE:") .forEach { setDynamic(it, false) } InTextDirectivesUtils.findListWithPrefixes(fileText, "SET_INT:") .map { it.split("=", limit = 2) } .forEach { (prop, value) -> setDynamic(prop, value.trim().toInt()) } InTextDirectivesUtils.findStringWithPrefixes(fileText, "RIGHT_MARGIN: ") ?.also { commonSettings.RIGHT_MARGIN = it.trim().toInt() } } } fun deconfigure(project: IProject) { KotlinCodeStyleProperties(ProjectScope(project)).apply { globalsOverridden = false codeStyleId?.also { KotlinCodeStyleManager.invalidate(it) } saveChanges() } } private fun Any.setDynamic(name: String, value: Any): Boolean = this::class.members.singleOrNull { it.name in setOf(name) } ?.let { when (it) { is KMutableProperty -> it.setter is KFunction -> it else -> null } } ?.call(this, value) ?.let { true } ?: false } ================================================ FILE: kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/utils/EditorTestUtils.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.testframework.utils; import org.eclipse.core.resources.IFile; import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.graphics.Point; import org.eclipse.ui.IEditorDescriptor; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.FileEditorInput; import org.jetbrains.kotlin.eclipse.ui.utils.EditorUtil; import org.jetbrains.kotlin.eclipse.ui.utils.LineEndUtil; import org.jetbrains.kotlin.testframework.editor.KotlinEditorTestCase; import org.junit.Assert; import org.junit.ComparisonFailure; public class EditorTestUtils { public static IEditorPart openInEditor(IFile file) throws PartInitException { IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); IWorkbenchPage page = window.getActivePage(); FileEditorInput fileEditorInput = new FileEditorInput(file); IEditorDescriptor defaultEditor = PlatformUI.getWorkbench().getEditorRegistry().getDefaultEditor( file.getName()); return page.openEditor(fileEditorInput, defaultEditor.getId()); } public static void assertByEditorWithErrorMessage(JavaEditor activeEditor, String expected, String message) { StyledText editorTextWidget = activeEditor.getViewer().getTextWidget(); assertByStringWithEditorWidgetAndErrorMessage(EditorUtil.getSourceCode(activeEditor), expected, editorTextWidget, message); } public static void assertByEditor(JavaEditor activeEditor, String expected) { assertByEditorWithErrorMessage(activeEditor, expected, ""); } private static void assertByStringWithEditorWidgetAndErrorMessage(String actual, String expected, StyledText editorTextWidget, String errorMessage) { int caretOffset = editorTextWidget.getCaretOffset(); Point selection = editorTextWidget.getSelection(); expected = expected.replaceAll(KotlinEditorTestCase.BREAK_TAG, System.lineSeparator()); int selectionStartOffset = selection.x; int selectionEndOffset = selection.y; if (expected.contains(KotlinEditorTestCase.CARET_TAG) && caretOffset != -1) { actual = actual.substring(0, caretOffset) + KotlinEditorTestCase.CARET_TAG + actual.substring(caretOffset); int caretTagLength = KotlinEditorTestCase.CARET_TAG.length(); if (selectionStartOffset > caretOffset) { selectionStartOffset += caretTagLength; } if (selectionEndOffset >= caretOffset) { selectionEndOffset += caretTagLength; } } // caret tag is expected to be absent if selection is present or to be // within selection if (expected.contains(KotlinEditorTestCase.SELECTION_TAG_OPEN) && selection.x != selection.y) { StringBuilder taggedBuilder = new StringBuilder(actual); // insert closing tag first, because then there's no need to recalc // end offset taggedBuilder.insert(selectionEndOffset, KotlinEditorTestCase.SELECTION_TAG_CLOSE); taggedBuilder.insert(selectionStartOffset, KotlinEditorTestCase.SELECTION_TAG_OPEN); actual = taggedBuilder.toString(); } try { Assert.assertEquals(LineEndUtil.removeAllCarriageReturns(expected).trim(), LineEndUtil.removeAllCarriageReturns(actual).trim()); } catch (ComparisonFailure e) { throw new ComparisonFailure(errorMessage, e.getExpected(), e.getActual()); } } } ================================================ FILE: kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/utils/ExpectedCompletionUtils.java ================================================ package org.jetbrains.kotlin.testframework.utils; import static org.jetbrains.kotlin.testframework.utils.InTextDirectivesUtils.getItems; import java.util.List; public class ExpectedCompletionUtils { private static final String EXIST_LINE_PREFIX = "EXIST:"; private static final String ABSENT_LINE_PREFIX = "ABSENT:"; private static final String NUMBER_LINE_PREFIX = "NUMBER:"; private static final String EXIST_JAVA_ONLY_LINE_PREFIX = "EXIST_JAVA_ONLY:"; private static final String ELEMENT_PREFIX = "ELEMENT:"; private static final String COMPLETION_CHAR_PREFIX = "COMPLETION_CHAR:"; private static final String INVOCATION_COUNT_PREFIX = "INVOCATION_COUNT:"; private static final String NOTHING_ELSE_PREFIX = "NOTHING_ELSE"; public static List itemsShouldAbsent(String fileText) { return getItems(fileText, ABSENT_LINE_PREFIX); } public static List itemsShouldExist(String fileText) { return getItems(fileText, EXIST_LINE_PREFIX); } public static boolean isNothingElseExpected(String fileText) { return !InTextDirectivesUtils.findListWithPrefixes(fileText, NOTHING_ELSE_PREFIX).isEmpty(); } public static String itemToComplete(String fileText) { List items = getItems(fileText, ELEMENT_PREFIX); if (!items.isEmpty()) { assert items.size() == 1 : "There should be only one item to complete"; return items.get(0); } return null; } public static Character getCompletionChar(String fileText) { List items = getItems(fileText, COMPLETION_CHAR_PREFIX); return !items.isEmpty() ? items.get(0).charAt(0) : null; } public static List itemsJavaOnlyShouldExists(String fileText) { return getItems(fileText, EXIST_JAVA_ONLY_LINE_PREFIX); } public static Integer numberOfItemsShouldPresent(String fileText) { List numbers = getItems(fileText, NUMBER_LINE_PREFIX); if (numbers.isEmpty()) { return null; } return new Integer(numbers.get(0)); } public static Boolean shouldHideNonVisibleMembers(String fileText) { List counts = getItems(fileText, INVOCATION_COUNT_PREFIX); if (counts.isEmpty()) { return true; } return new Integer(counts.get(0)) == 1; } } ================================================ FILE: kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/utils/InTextDirectivesUtils.java ================================================ package org.jetbrains.kotlin.testframework.utils; import java.io.BufferedReader; import java.io.IOException; import java.io.StringReader; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import com.intellij.openapi.util.text.StringUtil; import kotlin.text.StringsKt; // Source code is taken from org.jetbrains.kotlin.InTextDirectivesUtils public class InTextDirectivesUtils { public static String findStringWithPrefixes(String fileText, String... prefixes) { List strings = findListWithPrefixes(fileText, prefixes); if (strings.isEmpty()) { return null; } if (strings.size() != 1) { throw new IllegalStateException( "There is more than one string with given prefixes " + Arrays.toString(prefixes) + ":\n" + StringUtil.join(strings, "\n") + "\n" + "Use findListWithPrefixes() instead."); } return strings.get(0); } public static List findListWithPrefixes(String fileText, String... prefixes) { List result = new ArrayList(); for (String line : findLinesWithPrefixesRemoved(fileText, prefixes)) { String[] variants = line.split(","); for (String variant : variants) { result.add(StringUtil.unquoteString(variant.trim())); } } return result; } private static List findLinesWithPrefixesRemoved(String fileText, String... prefixes) { List result = new ArrayList(); List cleanedPrefixes = cleanDirectivesFromComments(Arrays.asList(prefixes)); for (String line : fileNonEmptyCommentedLines(fileText)) { for (String prefix : cleanedPrefixes) { if (!line.startsWith(prefix)) continue; String noPrefixLine = line.substring(prefix.length()); if (noPrefixLine.isEmpty() || Character.isWhitespace(noPrefixLine.charAt(0)) || Character.isWhitespace(prefix.charAt(prefix.length() - 1))) { result.add(noPrefixLine.trim()); break; } } } return result; } private static List cleanDirectivesFromComments(Collection prefixes) { List resultPrefixes = new ArrayList(); for (String prefix : prefixes) { if (prefix.startsWith("//")) { resultPrefixes.add(StringsKt.removePrefix(prefix, prefix.substring(0, 2)).trim()); } else { resultPrefixes.add(prefix.trim()); } } return resultPrefixes; } private static List fileNonEmptyCommentedLines(String fileText) { List result = new ArrayList(); try { BufferedReader reader = new BufferedReader(new StringReader(fileText)); try { String line; while ((line = reader.readLine()) != null) { line = line.trim(); if (line.startsWith("//")) { String uncommentedLine = line.substring(2).trim(); if (!uncommentedLine.isEmpty()) { result.add(StringUtil.trim(uncommentedLine)); } } } } finally { reader.close(); } } catch (IOException e) { throw new AssertionError(e); } return result; } // TODO: Parse JSon string from tests static List getItems(String fileText, String prefix) { List items = new ArrayList(); for (String itemStr : findLinesWithPrefixesRemoved(fileText, prefix)) { if (itemStr.startsWith("{")) continue; for (String item : itemStr.split(",")) { items.add(item.trim()); } } return items; } } ================================================ FILE: kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/utils/KotlinTestUtils.java ================================================ package org.jetbrains.kotlin.testframework.utils; import java.io.File; import java.io.IOException; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.Path; import org.eclipse.core.runtime.jobs.Job; import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor; import com.intellij.openapi.util.io.FileUtil; public class KotlinTestUtils { public enum Separator { TAB, SPACE; } public static final String ERROR_TAG_OPEN = ""; public static final String ERROR_TAG_CLOSE = ""; public static final String BR = "
"; public static String getText(String testPath) { try { File file = new File(testPath); return String.valueOf(FileUtil.loadFile(file)); } catch (IOException e) { throw new RuntimeException(e); } } public static String getNameByPath(String testPath) { return new Path(testPath).lastSegment(); } public static void joinBuildThread() { while (true) { try { Job.getJobManager().join(ResourcesPlugin.FAMILY_AUTO_BUILD, null); break; } catch (OperationCanceledException | InterruptedException e) { } } } public static void refreshWorkspace() { WorkspaceUtil.refreshWorkspace(); try { Job.getJobManager().join(ResourcesPlugin.FAMILY_MANUAL_REFRESH, new NullProgressMonitor()); } catch (OperationCanceledException | InterruptedException e) { e.printStackTrace(); } } public static int getCaret(JavaEditor javaEditor) { return javaEditor.getViewer().getTextWidget().getCaretOffset(); } public static String resolveTestTags(String text) { return text.replaceAll(ERROR_TAG_OPEN, "").replaceAll(ERROR_TAG_CLOSE, "").replaceAll(BR, System.lineSeparator()); } } ================================================ FILE: kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/utils/SourceFileData.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.testframework.utils; import java.io.File; import java.io.IOException; import java.util.regex.Matcher; import java.util.regex.Pattern; import com.intellij.openapi.util.io.FileUtil; public class SourceFileData { private final static String DEFAULT_PACKAGE_NAME = ""; private final static String JAVA_IDENTIFIER_REGEXP = "[_a-zA-Z]\\w*"; private final static String PACKAGE_REGEXP = "package\\s((" + JAVA_IDENTIFIER_REGEXP + ")(\\." + JAVA_IDENTIFIER_REGEXP + ")*)"; private final static Pattern PATTERN = Pattern.compile(PACKAGE_REGEXP); private final String fileName; private final String packageName; private final String content; public SourceFileData(String fileName, String content) { this.fileName = fileName; this.content = content; this.packageName = getPackageFromContent(content); } public SourceFileData(File file) throws IOException { this(file.getName(), FileUtil.loadFile(file)); } public String getFileName() { return fileName; } public String getPackageName() { return packageName; } public String getContent() { return content; } public static String getPackageFromContent(String content) { Matcher matcher = PATTERN.matcher(content); return matcher.find() ? matcher.group(1) : DEFAULT_PACKAGE_NAME; } } ================================================ FILE: kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/utils/TestJavaProject.java ================================================ /******************************************************************************* * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.testframework.utils; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; 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.IProjectDescription; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspace; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jdt.core.IClasspathEntry; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.launching.JavaRuntime; import org.jetbrains.kotlin.core.model.KotlinEnvironment; import org.jetbrains.kotlin.core.model.KotlinJavaManager; import org.jetbrains.kotlin.core.model.KotlinNature; import org.jetbrains.kotlin.core.utils.ProjectUtils; import com.intellij.lang.java.JavaLanguage; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.io.FileUtilRt; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiFileFactory; import com.intellij.psi.PsiJavaFile; public class TestJavaProject { public final static String SRC_FOLDER = "src"; private IProject project; private IJavaProject javaProject; private IPackageFragmentRoot sourceFolder; public TestJavaProject(String projectName) { this(projectName, null); } public TestJavaProject(String projectName, String location) { project = createProject(projectName, location); } private IProject createProject(String projectName, String location) { IWorkspace workspace = ResourcesPlugin.getWorkspace(); IWorkspaceRoot workspaceRoot = workspace.getRoot(); IProjectDescription projectDescription = workspace.newProjectDescription(projectName); if (location != null) { IPath rootPath = workspaceRoot.getLocation(); IPath locationPath = rootPath.append(location); projectDescription.setLocation(locationPath); } project = workspaceRoot.getProject(projectName); try { boolean projectExists = project.exists(); if (!projectExists) { project.create(projectDescription, null); } project.open(null); javaProject = JavaCore.create(project); if (!projectExists) { setNatureSpecificProperties(); setDefaultSettings(); IFolder outputFolder = createFolderIfNotExist("bin"); createOutputFolder(outputFolder); } } catch (CoreException e) { throw new RuntimeException(e); } return project; } public void setDefaultSettings() { try { javaProject.setRawClasspath(new IClasspathEntry[0], null); addSystemLibraries(); sourceFolder = createSourceFolder(SRC_FOLDER); } catch (CoreException e) { throw new RuntimeException(e); } } private void setNatureSpecificProperties() throws CoreException { IProjectDescription description = project.getDescription(); description.setNatureIds(new String[] { JavaCore.NATURE_ID }); project.setDescription(description, null); KotlinNature.Companion.addNature(project); } private IFile createFile(IContainer folder, String name, InputStream content) { IFile file = folder.getFile(new Path(name)); try { if (file.exists()) { file.delete(true, null); } file.create(content, true, null); } catch (CoreException e) { throw new RuntimeException(e); } return file; } public IFile createSourceFile(String pkg, String fileName, String content) throws CoreException { return createSourceFile(pkg, fileName, content, null); } public IFile createSourceFile(String pkg, String fileName, String content, Charset charset) throws CoreException { String ext = FileUtilRt.getExtension(fileName); String refinedFileName; if ("java".equals(ext)) { refinedFileName = getJavaClassName(content); if (refinedFileName != null) { refinedFileName += ".java"; } else { refinedFileName = fileName; } pkg = SourceFileData.getPackageFromContent(content); } else { refinedFileName = fileName; } Charset effectiveCharset = (charset == null) ? StandardCharsets.UTF_8 : charset; IPackageFragment fragment = createPackage(pkg); IFile file = createFile((IFolder) fragment.getResource(), refinedFileName, new ByteArrayInputStream(content.getBytes(effectiveCharset))); if (charset != null) { file.setCharset(charset.name(), null); } return file; } public IPackageFragment createPackage(String name) throws CoreException { if (sourceFolder == null) { sourceFolder = createSourceFolder(SRC_FOLDER); } return sourceFolder.createPackageFragment(name, true, null); } private void createOutputFolder(IFolder outputFolder) throws JavaModelException { IPath outputLocation = outputFolder.getFullPath(); javaProject.setOutputLocation(outputLocation, null); } public IPackageFragmentRoot createSourceFolder(String srcFolderName) throws CoreException { IFolder folder = createFolderIfNotExist(srcFolderName); IPackageFragmentRoot root = javaProject.getPackageFragmentRoot(folder); for (IClasspathEntry entry : javaProject.getResolvedClasspath(false)) { if (folder.getFullPath().equals(entry.getPath())) { return root; } } IClasspathEntry[] oldEntries = javaProject.getRawClasspath(); IClasspathEntry[] newEntries = new IClasspathEntry[oldEntries.length + 1]; System.arraycopy(oldEntries, 0, newEntries, 0, oldEntries.length); newEntries[oldEntries.length] = JavaCore.newSourceEntry(root.getPath()); javaProject.setRawClasspath(newEntries, null); return root; } public IFolder createFolderIfNotExist(String name) throws CoreException { IFolder folder = project.getFolder(name); if (!folder.exists()) { folder.create(false, true, null); } return folder; } public KotlinEnvironment getKotlinEnvironment() { return KotlinEnvironment.Companion.getEnvironment(javaProject.getProject()); } public IJavaProject getJavaProject() { return javaProject; } public IProject getProject() { return project; } public void addKotlinRuntime() throws CoreException { ProjectUtils.addKotlinRuntime(javaProject); } public void addLibrary(IPath libraryPath, IPath sourcePath) throws JavaModelException { IClasspathEntry libraryEntry = JavaCore.newLibraryEntry(libraryPath, sourcePath, null); ProjectUtils.addContainerEntryToClasspath(javaProject, libraryEntry); } private void addSystemLibraries() throws JavaModelException { ProjectUtils.addContainerEntryToClasspath(javaProject, JavaRuntime.getDefaultJREContainerEntry()); } public void clean() { try { cleanSourceFolder(); IFolder outputFolder = ProjectUtils.getDefaultOutputFolder(getJavaProject()); ProjectUtils.cleanFolder(outputFolder); ProjectUtils.cleanFolder(KotlinJavaManager.INSTANCE.getKotlinBinFolderFor(project)); } catch (JavaModelException e) { throw new RuntimeException(e); } catch (CoreException e) { throw new RuntimeException(e); } } private String getJavaClassName(String content) { PsiJavaFile javaPsiFile = createJavaPsiFile(content, getKotlinEnvironment().getProject()); PsiClass[] classes = javaPsiFile.getClasses(); return classes.length > 0 ? classes[0].getName() : null; } private PsiJavaFile createJavaPsiFile(String text, Project ideaProject) { return (PsiJavaFile) PsiFileFactory.getInstance(ideaProject).createFileFromText("test.java", JavaLanguage.INSTANCE, text); } private void cleanSourceFolder() throws CoreException { for (IClasspathEntry resolvedCP : javaProject.getResolvedClasspath(true)) { if (resolvedCP.getEntryKind() == IClasspathEntry.CPE_SOURCE) { IResource sourceFolder = findResourceInProject(resolvedCP.getPath()); ProjectUtils.cleanFolder((IContainer) sourceFolder); } } } private IResource findResourceInProject(IPath path) { return ResourcesPlugin.getWorkspace().getRoot().findMember(path); } } ================================================ FILE: kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/utils/TypingUtils.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.testframework.utils; import static org.jetbrains.kotlin.testframework.utils.InTextDirectivesUtils.getItems; import java.util.List; public class TypingUtils { private static final String TYPE_PREFIX = "TYPE: "; public static Character typedCharacter(String fileText) { List items = getItems(fileText, TYPE_PREFIX); return !items.isEmpty() ? items.get(0).charAt(0) : null; } public static String typedText(String fileText) { return getItems(fileText, TYPE_PREFIX).get(0); } } ================================================ FILE: kotlin-eclipse-test-framework/src/org/jetbrains/kotlin/testframework/utils/WorkspaceUtil.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.testframework.utils; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; public class WorkspaceUtil { public static void refreshWorkspace() { try { IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects(); for (IProject project : projects) { project.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor()); } } catch (CoreException e) { e.printStackTrace(); } } } ================================================ FILE: kotlin-eclipse-ui/META-INF/MANIFEST.MF ================================================ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: kotlin-eclipse-ui Bundle-SymbolicName: org.jetbrains.kotlin.ui;singleton:=true Bundle-Version: 0.8.24.qualifier Bundle-Activator: org.jetbrains.kotlin.ui.Activator Bundle-Vendor: JetBrains Require-Bundle: org.eclipse.ui, org.eclipse.core.runtime, org.jetbrains.kotlin.core, org.eclipse.jface.text, org.eclipse.ui.editors;visibility:=reexport, org.jetbrains.kotlin.bundled-compiler, org.eclipse.debug.ui, org.eclipse.jdt.debug.ui, org.eclipse.jdt.ui, org.eclipse.jdt.junit, org.eclipse.jdt.debug, org.eclipse.compare, org.eclipse.search, org.eclipse.jdt.core.manipulation, org.eclipse.ltk.core.refactoring, org.eclipse.ltk.ui.refactoring, org.eclipse.equinox.p2.operations, org.eclipse.equinox.p2.core, org.eclipse.equinox.p2.metadata, org.eclipse.equinox.p2.engine, org.eclipse.equinox.p2.director, org.eclipse.core.variables Bundle-ActivationPolicy: lazy Import-Package: com.google.common.collect, org.jetbrains.kotlin.nj2k, org.jetbrains.kotlin.idea.j2k, org.jetbrains.kotlin.nj2k.postProcessing, org.eclipse.core.expressions, org.eclipse.core.resources, org.eclipse.jdt.core, org.eclipse.jdt.core.compiler, org.eclipse.jdt.core.dom, org.eclipse.jdt.core.search, org.eclipse.jdt.debug.ui.launchConfigurations, org.eclipse.jdt.internal.compiler.classfmt, org.eclipse.jdt.internal.compiler.env, org.eclipse.jdt.internal.core, org.eclipse.jdt.junit.launcher, org.eclipse.jdt.launching, org.eclipse.jdt.ui, org.eclipse.swt.graphics, org.eclipse.ui, org.eclipse.ui.console, org.eclipse.ui.dialogs, org.eclipse.ui.ide, org.eclipse.ui.ide.undo, org.eclipse.ui.internal.texteditor.quickdiff, org.eclipse.ui.part, org.eclipse.ui.texteditor.link, org.eclipse.ui.texteditor.templates, org.eclipse.ui.views.contentoutline, org.eclipse.ui.wizards.newresource, org.jetbrains.kotlin.idea.util Bundle-RequiredExecutionEnvironment: JavaSE-17 Export-Package: org.jetbrains.kotlin.eclipse.ui.utils, org.jetbrains.kotlin.ui, org.jetbrains.kotlin.ui.builder, org.jetbrains.kotlin.ui.commands.findReferences, org.jetbrains.kotlin.ui.commands.j2k, org.jetbrains.kotlin.ui.editors, org.jetbrains.kotlin.ui.editors.annotations, org.jetbrains.kotlin.ui.editors.codeassist, org.jetbrains.kotlin.ui.editors.highlighting, org.jetbrains.kotlin.ui.editors.navigation, org.jetbrains.kotlin.ui.editors.organizeImports, org.jetbrains.kotlin.ui.editors.quickassist, org.jetbrains.kotlin.ui.editors.quickfix, org.jetbrains.kotlin.ui.editors.selection, org.jetbrains.kotlin.ui.formatter, org.jetbrains.kotlin.ui.launch, org.jetbrains.kotlin.ui.launch.junit, org.jetbrains.kotlin.ui.navigation, org.jetbrains.kotlin.ui.overrideImplement, org.jetbrains.kotlin.ui.refactorings.extract, org.jetbrains.kotlin.ui.refactorings.rename, org.jetbrains.kotlin.ui.search, org.jetbrains.kotlin.ui.editors.hover ================================================ FILE: kotlin-eclipse-ui/Run Kotlin Plugin with Equinox Weaving.launch ================================================ ================================================ FILE: kotlin-eclipse-ui/Run with open port.launch ================================================ ================================================ FILE: kotlin-eclipse-ui/build.properties ================================================ ############################################################################### # Copyright 2000-2014 JetBrains s.r.o. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # ############################################################################### source.. = src/ output.. = bin/ bin.includes = META-INF/,\ .,\ plugin.xml,\ icons/,\ templates/,\ schema/ src.includes = icons/,\ templates/,\ ================================================ FILE: kotlin-eclipse-ui/plugin.xml ================================================ Create a new Kotlin project Create a new Kotlin file Create a new Kotlin class Create a new Kotlin sealed class Create a new Kotlin interface Create a new Kotlin sealed interface Create a new Kotlin object Create a new Kotlin enum Create a new Kotlin data class Create a new Kotlin annotation Open Kotlin pespective ================================================ FILE: kotlin-eclipse-ui/pom.xml ================================================ 4.0.0 ../pom.xml kotlin.eclipse kotlin.eclipse.plugin 0.8.24-SNAPSHOT org.jetbrains.kotlin.ui eclipse-plugin src org.jetbrains.kotlin kotlin-maven-plugin ${kotlin.version} 17 compile process-sources compile org.apache.maven.plugins maven-compiler-plugin 3.10.1 17 ================================================ FILE: kotlin-eclipse-ui/schema/org.jetbrains.kotlin.ui.editor.textHover.exsd ================================================ [Enter description of this extension point.] A human readable name of this provider The name of a class that implements interface org.jetbrains.kotlin.ui.editors.hover.KotlinEditorTextHover [Enter the first release in which this extension point appears.] [Enter extension point usage example here.] [Enter API information here.] [Enter information about supplied implementation of this extension point.] ================================================ FILE: kotlin-eclipse-ui/src/org/jetbrains/kotlin/eclipse/ui/utils/EditorUtil.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.eclipse.ui.utils; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.TextUtilities; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.editors.text.TextFileDocumentProvider; import org.eclipse.ui.texteditor.AbstractTextEditor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.core.builder.KotlinPsiManager; import org.jetbrains.kotlin.core.log.KotlinLogger; import org.jetbrains.kotlin.core.references.ReferenceUtilsKt; import org.jetbrains.kotlin.psi.KtElement; import org.jetbrains.kotlin.psi.KtFile; import org.jetbrains.kotlin.psi.KtReferenceExpression; import org.jetbrains.kotlin.ui.editors.KotlinEditor; import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; public class EditorUtil { @Nullable public static IFile getFile(@NotNull IEditorPart editor) { return editor.getEditorInput().getAdapter(IFile.class); } @NotNull public static String getSourceCode(@NotNull KotlinEditor editor) { return editor.getDocument().get(); } @NotNull public static String getSourceCode(@NotNull AbstractTextEditor editor) { return getDocument(editor).get(); } @NotNull public static IDocument getDocument(@NotNull AbstractTextEditor editor) { return editor.getDocumentProvider().getDocument(editor.getEditorInput()); } @NotNull public static IDocument getDocument(@NotNull IFile file) { TextFileDocumentProvider provider = new TextFileDocumentProvider(); try { provider.connect(file); return provider.getDocument(file); } catch (CoreException e) { KotlinLogger.logAndThrow(e); } finally { provider.disconnect(file); } throw new RuntimeException(); } public static String getDocumentLineDelimiter(@NotNull KotlinEditor editor) { return TextUtilities.getDefaultLineDelimiter(editor.getDocument()); } @Nullable public static PsiElement getPsiElement(@NotNull KotlinEditor editor, int offset) { KtFile jetFile = editor.getParsedFile(); if (jetFile != null) { int caretOffset = LineEndUtil.convertCrToDocumentOffset(editor.getDocument(), offset); return jetFile.findElementAt(caretOffset); } else { KotlinLogger.logError("Failed to retrieve IFile from editor " + editor, null); } return null; } @Nullable public static KtElement getJetElement(@NotNull KotlinEditor editor, int offset) { PsiElement psiElement = getPsiElement(editor, offset); return psiElement != null ? PsiTreeUtil.getNonStrictParentOfType(psiElement, KtElement.class) : null; } @Nullable public static KtReferenceExpression getReferenceExpression(@NotNull KotlinEditor editor, int offset) { KtFile ktFile = editor.getParsedFile(); if (ktFile == null) return null; int documentOffset = LineEndUtil.convertCrToDocumentOffset(editor.getDocument(), offset); PsiElement psiExpression = ktFile.findElementAt(documentOffset); if (psiExpression == null) return null; return ReferenceUtilsKt.getReferenceExpression(psiExpression); } @Nullable public static KtFile updatePsiFile(@NotNull KotlinEditor editor) { IFile file = editor.getEclipseFile(); return file != null ? KotlinPsiManager.getKotlinFileIfExist(file, editor.getDocument().get()) : null; } } ================================================ FILE: kotlin-eclipse-ui/src/org/jetbrains/kotlin/eclipse/ui/utils/IndenterUtil.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.eclipse.ui.utils; import org.eclipse.ui.editors.text.EditorsUI; import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants; import org.jetbrains.kotlin.lexer.KtTokens; import com.intellij.psi.impl.source.tree.LeafPsiElement; public class IndenterUtil { public static final char SPACE_CHAR = ' '; public static final String SPACE_STRING = Character.toString(SPACE_CHAR); public static final char TAB_CHAR = '\t'; public static final String TAB_STRING = Character.toString(TAB_CHAR); public static String createWhiteSpace(int curIndent, int countBreakLines, String lineSeparator) { StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < countBreakLines; i++) { stringBuilder.append(lineSeparator); } String whiteSpace = getIndentString(); for (int i = 0; i < curIndent; i++) { stringBuilder.append(whiteSpace); } return stringBuilder.toString(); } public static String createWhiteSpaceByRawIndent(int rawIndent, int countBreakLines, String lineSeparator) { StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < countBreakLines; i++) { stringBuilder.append(lineSeparator); } for (int i = 0; i < rawIndent; i++) { stringBuilder.append(SPACE_CHAR); } return stringBuilder.toString(); } public static String getIndentString() { if (isSpacesForTabs()) { StringBuilder result = new StringBuilder(); for (int i = 0; i < getDefaultIndent(); i++) { result.append(SPACE_CHAR); } return result.toString(); } else { return new Character(TAB_CHAR).toString(); } } public static int getLineSeparatorsOccurences(String text) { int result = 0; for (char c : text.toCharArray()) { if (c == LineEndUtil.NEW_LINE_CHAR) { result++; } } return result; } public static boolean isNewLine(LeafPsiElement psiElement) { return psiElement.getElementType() == KtTokens.WHITE_SPACE && psiElement.getText().contains(LineEndUtil.NEW_LINE_STRING); } public static int getDefaultIndent() { return EditorsUI.getPreferenceStore().getInt(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH); } public static int getDefaultIndentSize() { if (isSpacesForTabs()) { return getDefaultIndent(); } else { return 1; } } public static boolean isSpacesForTabs() { return EditorsUI.getPreferenceStore().getBoolean(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_SPACES_FOR_TABS); } public static boolean isWhiteSpaceChar(char c) { return c == SPACE_CHAR || c == TAB_CHAR; } public static boolean isWhiteSpaceOrNewLine(char c) { return c == SPACE_CHAR || c == TAB_CHAR || c == LineEndUtil.NEW_LINE_CHAR; } } ================================================ FILE: kotlin-eclipse-ui/src/org/jetbrains/kotlin/eclipse/ui/utils/KotlinEclipseScope.kt ================================================ package org.jetbrains.kotlin.eclipse.ui.utils import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob object KotlinEclipseScope : CoroutineScope by CoroutineScope(SupervisorJob() + Dispatchers.IO) ================================================ FILE: kotlin-eclipse-ui/src/org/jetbrains/kotlin/eclipse/ui/utils/KotlinImageProvider.kt ================================================ /******************************************************************************* * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.eclipse.ui.utils import org.eclipse.jdt.ui.ISharedImages import org.eclipse.jdt.ui.JavaUI import org.eclipse.swt.graphics.Image import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.psi.KtClassOrObject import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtFunction import org.jetbrains.kotlin.psi.KtVariableDeclaration object KotlinImageProvider { fun getImage(descriptor: DeclarationDescriptor): Image? { return when(descriptor) { is ClassDescriptor, is TypeParameterDescriptor, is TypeAliasDescriptor -> getImageFromJavaUI(ISharedImages.IMG_OBJS_CLASS) is FunctionDescriptor -> getImageFromJavaUI(ISharedImages.IMG_OBJS_PUBLIC) is VariableDescriptor -> getImageFromJavaUI(ISharedImages.IMG_FIELD_PUBLIC) is PackageViewDescriptor -> getImageFromJavaUI(ISharedImages.IMG_OBJS_PACKAGE) else -> null } } fun getImage(element: KtElement): Image? { return when(element) { is KtClassOrObject -> getImageFromJavaUI(ISharedImages.IMG_OBJS_CLASS) is KtFunction -> getImageFromJavaUI(ISharedImages.IMG_OBJS_PUBLIC) is KtVariableDeclaration -> getImageFromJavaUI(ISharedImages.IMG_FIELD_PUBLIC) else -> null } } private fun getImageFromJavaUI(imageName: String): Image = JavaUI.getSharedImages().getImage(imageName) } ================================================ FILE: kotlin-eclipse-ui/src/org/jetbrains/kotlin/eclipse/ui/utils/LineEndUtil.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.eclipse.ui.utils; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.TextUtilities; import org.jetbrains.annotations.NotNull; import com.intellij.openapi.util.TextRange; public class LineEndUtil { public static final char CARRIAGE_RETURN_CHAR = '\r'; public static final String CARRIAGE_RETURN_STRING = Character.toString(CARRIAGE_RETURN_CHAR); public static final char NEW_LINE_CHAR = '\n'; public static final String NEW_LINE_STRING = Character.toString(NEW_LINE_CHAR); public static int convertLfToDocumentOffset(@NotNull String lfText, int lfOffset, @NotNull IDocument document) { String documentLineDelimiter = TextUtilities.getDefaultLineDelimiter(document); if (documentLineDelimiter.length() == 1) { return lfOffset; } assertLineSeparator(documentLineDelimiter); // In CrLf move to new line takes 2 char instead of 1 in Lf return lfOffset + offsetToLineNumber(lfText, lfOffset); } private static int offsetToLineNumber(String lfText, int offset) { int line = 0; int curOffset = 0; while (curOffset < offset) { if (curOffset == lfText.length()) { break; } char c = lfText.charAt(curOffset); if (c == NEW_LINE_CHAR) { line++; } else if (c == CARRIAGE_RETURN_CHAR) { throw new IllegalArgumentException("Given text shouldn't contain \\r char"); } curOffset++; } return line; } public static int convertCrToDocumentOffset(@NotNull IDocument document, int crOffset) { return convertCrToDocumentOffset(document.get(), crOffset, document); } public static int convertCrToDocumentOffset(@NotNull String crText, int crOffset, @NotNull IDocument document) { String defaultLineDelimiter = TextUtilities.getDefaultLineDelimiter(document); if (defaultLineDelimiter.length() == 1) { return crOffset; } assertLineSeparator(defaultLineDelimiter); return crOffset - countCrToLineNumber(crText, crOffset); } private static int countCrToLineNumber(String lfText, int offset) { int countCR = 0; int curOffset = 0; while (curOffset < offset) { if (curOffset == lfText.length()) { break; } char c = lfText.charAt(curOffset); if (c == CARRIAGE_RETURN_CHAR) { countCR++; } curOffset++; } return countCR; } private static void assertLineSeparator(String osLineSeparator) { assert osLineSeparator.equals(CARRIAGE_RETURN_STRING + NEW_LINE_STRING) : "Only \r\n is expected as multi char line separator"; } public static String removeAllCarriageReturns(String s) { return s.replaceAll(CARRIAGE_RETURN_STRING, ""); } @NotNull public static TextRange lfRangeFromCrRange(@NotNull TextRange crRange, @NotNull IDocument document) { int startOffset = LineEndUtil.convertCrToDocumentOffset(document, crRange.getStartOffset()); int endOffset = LineEndUtil.convertCrToDocumentOffset(document, crRange.getEndOffset()); return new TextRange(startOffset, endOffset); } @NotNull public static TextRange crRangeFromLfRange(@NotNull String lfText, @NotNull TextRange lfRange, @NotNull IDocument document) { int startOffset = LineEndUtil.convertLfToDocumentOffset(lfText, lfRange.getStartOffset(), document); int endOffset = LineEndUtil.convertLfToDocumentOffset(lfText, lfRange.getEndOffset(), document); return new TextRange(startOffset, endOffset); } public static int convertLfOffsetForMixedDocument(@NotNull IDocument document, int lfOffset) { int countCRs = 0; int current = 0; String text = document.get(); while (current - countCRs < lfOffset) { if (text.charAt(current) == CARRIAGE_RETURN_CHAR) { countCRs++; } current++; } return current; } } ================================================ FILE: kotlin-eclipse-ui/src/org/jetbrains/kotlin/eclipse/ui/utils/ProjectScopedPreferenceUtils.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.eclipse.ui.utils; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.ProjectScope; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.ui.Activator; import org.osgi.service.prefs.BackingStoreException; public class ProjectScopedPreferenceUtils { @NotNull private static IEclipsePreferences getPreferences(@NotNull final IProject project) { return new ProjectScope(project).getNode(Activator.Companion.getPLUGIN_ID()); } public static boolean getBooleanPreference(@NotNull final IProject project, @NotNull final String key, final boolean defaultValue) { return getPreferences(project).getBoolean(key, defaultValue); } public static void putBooleanPreference(@NotNull final IProject project, @NotNull final String key, final boolean value) throws BackingStoreException { IEclipsePreferences preferences = getPreferences(project); preferences.putBoolean(key, value); preferences.flush(); } } ================================================ FILE: kotlin-eclipse-ui/src/org/jetbrains/kotlin/eclipse/ui/utils/analyzeUtils.kt ================================================ package org.jetbrains.kotlin.eclipse.ui.utils import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.ui.editors.KotlinEditor import org.jetbrains.kotlin.core.utils.getBindingContext fun KotlinEditor.getBindingContext(): BindingContext? = parsedFile?.getBindingContext() ================================================ FILE: kotlin-eclipse-ui/src/org/jetbrains/kotlin/eclipse/ui/utils/offsetUtils.kt ================================================ /******************************************************************************* * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.eclipse.ui.utils import com.intellij.psi.PsiElement import org.eclipse.jface.text.IDocument import org.jetbrains.kotlin.psi.KtFile fun PsiElement.getEndLfOffset(document: IDocument): Int { return LineEndUtil.convertLfToDocumentOffset(this.getContainingFile().getText(), this.getTextRange().getEndOffset(), document) } fun PsiElement.getTextDocumentOffset(document: IDocument): Int { return getOffsetByDocument(document, getTextOffset()) } fun PsiElement.getOffsetByDocument(document: IDocument, psiOffset: Int): Int { return LineEndUtil.convertLfToDocumentOffset(this.getContainingFile().getText(), psiOffset, document) } fun KtFile.findElementByDocumentOffset(offset: Int, document: IDocument): PsiElement? { val offsetWithoutCr = LineEndUtil.convertCrToDocumentOffset(document, offset); return this.findElementAt(offsetWithoutCr) } ================================================ FILE: kotlin-eclipse-ui/src/org/jetbrains/kotlin/perspective/KotlinPerspectiveFactory.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.perspective; import org.eclipse.debug.ui.IDebugUIConstants; import org.eclipse.jdt.ui.JavaUI; import org.eclipse.ui.IPageLayout; import org.eclipse.ui.IPerspectiveFactory; public class KotlinPerspectiveFactory implements IPerspectiveFactory { @Override public void createInitialLayout(IPageLayout layout) { layout.addActionSet(IDebugUIConstants.LAUNCH_ACTION_SET); layout.addActionSet(JavaUI.ID_ACTION_SET); } } ================================================ FILE: kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/BasePropertyPage.kt ================================================ package org.jetbrains.kotlin.preferences import org.eclipse.swt.SWT import org.eclipse.swt.layout.GridLayout import org.eclipse.swt.widgets.Composite import org.eclipse.swt.widgets.Control import org.eclipse.ui.dialogs.PropertyPage import org.jetbrains.kotlin.core.preferences.Preferences import org.jetbrains.kotlin.swt.builders.asView import org.jetbrains.kotlin.swt.builders.layout abstract class BasePropertyPage : PropertyPage() { protected abstract val properties: Preferences private lateinit var rootView: Composite protected abstract fun createUI(parent: Composite): Control protected open fun afterOk() {} final override fun createContents(parent: Composite): Control { rootView = Composite(parent, SWT.NONE).apply { layout = GridLayout().apply { marginWidth = 0 marginHeight = 0 } } createUI(rootView).asView .layout(horizontalGrab = true, verticalGrab = true) return rootView } final override fun performOk(): Boolean { properties.saveChanges() afterOk() return super.performOk() } final override fun performCancel(): Boolean { properties.cancelChanges() return super.performCancel() } final override fun performDefaults() { properties.loadDefaults() // Recreate view rootView.children.forEach { it.dispose() } createUI(rootView).asView .layout(horizontalGrab = true, verticalGrab = true) rootView.layout() super.performDefaults() } } ================================================ FILE: kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/EditorPreferencePage.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.preferences; import org.eclipse.jface.preference.PreferencePage; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; public class EditorPreferencePage extends PreferencePage implements IWorkbenchPreferencePage { public EditorPreferencePage() { } public EditorPreferencePage(String title) { super(title); } public EditorPreferencePage(String title, ImageDescriptor image) { super(title, image); } @Override public void init(IWorkbench workbench) { } @Override protected Control createContents(Composite parent) { return null; } } ================================================ FILE: kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/KotlinPreferenceInitializer.kt ================================================ /******************************************************************************* * Copyright 2000-2016 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.preferences import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer import org.jetbrains.kotlin.ui.Activator import org.jetbrains.kotlin.ui.KotlinPluginUpdater import java.util.Random import org.jetbrains.kotlin.core.preferences.CompilerPlugin import org.eclipse.jface.preference.IPreferenceStore class KotlinPreferenceInitializer : AbstractPreferenceInitializer() { override fun initializeDefaultPreferences() { val kotlinStore = Activator.getDefault().preferenceStore with(kotlinStore) { setDefault(KotlinPluginUpdater.LAST_UPDATE_CHECK, 0L) setDefault(KotlinPluginUpdater.USER_ID, 0L) } } } ================================================ FILE: kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/KotlinPreferencePage.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.preferences; import org.eclipse.jface.preference.PreferencePage; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.ui.IWorkbench; import org.eclipse.ui.IWorkbenchPreferencePage; public class KotlinPreferencePage extends PreferencePage implements IWorkbenchPreferencePage { public KotlinPreferencePage() { } public KotlinPreferencePage(String title) { super(title); } public KotlinPreferencePage(String title, ImageDescriptor image) { super(title, image); } @Override public void init(IWorkbench workbench) { } @Override protected Control createContents(Composite parent) { return null; } } ================================================ FILE: kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/KotlinTemplatePreferencePage.java ================================================ /******************************************************************************* * Copyright 2000-2014 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *******************************************************************************/ package org.jetbrains.kotlin.preferences; import org.eclipse.ui.texteditor.templates.TemplatePreferencePage; import org.jetbrains.kotlin.ui.Activator; import org.jetbrains.kotlin.ui.editors.templates.KotlinTemplateManager; public class KotlinTemplatePreferencePage extends TemplatePreferencePage { public KotlinTemplatePreferencePage() { setPreferenceStore(Activator.Companion.getDefault().getPreferenceStore()); setTemplateStore(KotlinTemplateManager.INSTANCE.getTemplateStore()); setContextTypeRegistry(KotlinTemplateManager.INSTANCE.getContextTypeRegistry()); } } ================================================ FILE: kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/building/ProjectBuildingPropertyPage.kt ================================================ package org.jetbrains.kotlin.preferences.building import org.eclipse.core.resources.IProject import org.eclipse.core.resources.ProjectScope import org.eclipse.swt.widgets.Composite import org.eclipse.swt.widgets.Control import org.eclipse.ui.IWorkbenchPropertyPage import org.jetbrains.kotlin.core.preferences.KotlinBuildingProperties import org.jetbrains.kotlin.preferences.BasePropertyPage import org.jetbrains.kotlin.preferences.views.buildingPropertiesView import org.jetbrains.kotlin.swt.builders.View import org.jetbrains.kotlin.swt.builders.asView import org.jetbrains.kotlin.swt.builders.checkbox import org.jetbrains.kotlin.swt.builders.enabled import org.jetbrains.kotlin.swt.builders.layout import org.jetbrains.kotlin.swt.builders.separator import org.jetbrains.kotlin.utils.LazyObservable class ProjectBuildingPropertyPage : BasePropertyPage(), IWorkbenchPropertyPage { // project must be lazy initialized, because getElement() called during construction of page object returns null val project: IProject by lazy { element.getAdapter(IProject::class.java) } private var overrideFlag by LazyObservable({ properties.globalsOverridden }) { _, _, v -> properties.globalsOverridden = v settingsView.enabled = v } private lateinit var settingsView: View override val properties by lazy { KotlinBuildingProperties(ProjectScope(project)) } override fun createUI(parent: Composite): Control = parent.asView.apply { checkbox(::overrideFlag, "Enable project speciffic settings") separator { layout(horizontalGrab = true) } settingsView = buildingPropertiesView(properties) { enabled = properties.globalsOverridden } }.control } ================================================ FILE: kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/building/WorkspaceBuildingPropertyPage.kt ================================================ package org.jetbrains.kotlin.preferences.building import org.eclipse.swt.widgets.Composite import org.eclipse.swt.widgets.Control import org.eclipse.ui.IWorkbench import org.eclipse.ui.IWorkbenchPreferencePage import org.jetbrains.kotlin.core.preferences.KotlinBuildingProperties import org.jetbrains.kotlin.preferences.BasePropertyPage import org.jetbrains.kotlin.preferences.views.buildingPropertiesView import org.jetbrains.kotlin.swt.builders.asView class WorkspaceBuildingPropertyPage : BasePropertyPage(), IWorkbenchPreferencePage { override val properties = KotlinBuildingProperties.workspaceInstance override fun init(workbench: IWorkbench?) { } override fun createUI(parent: Composite): Control = parent.asView .buildingPropertiesView(properties) { onIsValidChanged = { setValid(it) } } .control } ================================================ FILE: kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/compiler/CompilerPluginDialog.kt ================================================ package org.jetbrains.kotlin.preferences.compiler import org.eclipse.jface.dialogs.IDialogConstants import org.eclipse.jface.dialogs.MessageDialog import org.eclipse.jface.dialogs.TrayDialog import org.eclipse.swt.SWT import org.eclipse.swt.layout.GridLayout import org.eclipse.swt.widgets.Composite import org.eclipse.swt.widgets.Control import org.eclipse.swt.widgets.Shell import org.jetbrains.kotlin.core.preferences.CompilerPlugin import org.jetbrains.kotlin.core.preferences.PreferencesCollection import org.jetbrains.kotlin.swt.builders.* class CompilerPluginDialog( shell: Shell, private val allPlugins: PreferencesCollection, private val plugin: CompilerPlugin? ) : TrayDialog(shell) { private var keyField = plugin?.key private var pathField = plugin?.jarPath private var argsField = plugin?.args?.joinToString(separator = "\n") private val newKey: String get() = keyField?.trim() ?: "" override fun createDialogArea(parent: Composite): Control = parent.asView.gridContainer(cols = 2) { (control.layout as GridLayout).marginTop = 10 label("Plugin name:") textField(::keyField, style = SWT.BORDER) { layout(horizontalGrab = true) } label("Path to jar:") textField(::pathField, style = SWT.BORDER) { layout(horizontalGrab = true) } group("Plugin options:") { layout(horizontalSpan = 2, horizontalGrab = true, verticalGrab = true) textField(::argsField, style = SWT.BORDER or SWT.MULTI or SWT.V_SCROLL) { layout(suggestedHeight = 200, suggestedWidth = 450) } label("Note: plugin options should match the := pattern") } }.control override fun configureShell(newShell: Shell) { super.configureShell(newShell) newShell.text = if (plugin == null) "New compiler plugin" else "Edit compiler plugin" } override fun isHelpAvailable() = false override fun buttonPressed(buttonId: Int) { val successful = try { when { buttonId != IDialogConstants.OK_ID -> true keyField.isNullOrBlank() -> throw ValidationException("Plugin name cannot be blank") plugin != null && newKey == plugin.key -> { with(plugin) { jarPath = pathField?.trim() args = processArgs() } true } newKey in allPlugins -> throw ValidationException("Plugin with chosen name already exists") else -> { plugin?.delete() with(allPlugins[newKey]) { jarPath = pathField?.trim() active = plugin?.active ?: true args = processArgs() } true } } } catch (e: ValidationException) { MessageDialog.openError(shell, "Validation error", e.message) false } if (successful) { super.buttonPressed(buttonId) } } private fun processArgs() : List { val processedArgs = argsField.orEmpty() .lineSequence() .map(String::trim) .filterNot(String::isEmpty) .toList() processedArgs.find { """.+:.+=.+""".toRegex().matchEntire(it) == null }?.also { throw ValidationException("$it does not match the := pattern.") } val pluginPrefixes = processedArgs.map { """^.+:""".toRegex().find(it)?.value } .toSet() if (pluginPrefixes.size > 1) { throw ValidationException("Plugin arguments have different prefixes") } return processedArgs } override fun createButtonsForButtonBar(parent: Composite) { createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true) createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false) } } private class ValidationException(message: String): Exception(message) ================================================ FILE: kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/compiler/ProjectCompilerPropertyPage.kt ================================================ package org.jetbrains.kotlin.preferences.compiler import org.eclipse.core.resources.IProject import org.eclipse.core.resources.IncrementalProjectBuilder import org.eclipse.swt.widgets.Composite import org.eclipse.swt.widgets.Control import org.eclipse.ui.IWorkbenchPropertyPage import org.jetbrains.kotlin.core.model.KotlinEnvironment import org.jetbrains.kotlin.preferences.BasePropertyPage import org.jetbrains.kotlin.preferences.views.projectCompilerPropertiesView import org.jetbrains.kotlin.swt.builders.asView class ProjectCompilerPropertyPage : BasePropertyPage(), IWorkbenchPropertyPage { // project must be lazy initialized, because getElement() called during construction of page object returns null val project: IProject by lazy { element.getAdapter(IProject::class.java) } override val properties by lazy { KotlinEnvironment.getEnvironment(project).projectCompilerProperties } override fun createUI(parent: Composite): Control = parent.asView .projectCompilerPropertiesView(properties) { onIsValidChanged = { setValid(it) } } .control override fun afterOk() { RebuildJob { monitor -> KotlinEnvironment.removeEnvironment(project) project.build(IncrementalProjectBuilder.FULL_BUILD, monitor) }.schedule() } } ================================================ FILE: kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/compiler/RebuildJob.kt ================================================ package org.jetbrains.kotlin.preferences.compiler import org.eclipse.core.runtime.CoreException import org.eclipse.core.runtime.IProgressMonitor import org.eclipse.core.runtime.IStatus import org.eclipse.core.runtime.Status import org.eclipse.core.runtime.jobs.Job import org.jetbrains.kotlin.core.Activator class RebuildJob(private val rebuildTask: (IProgressMonitor?) -> Unit) : Job("Rebuilding workspace") { init { priority = BUILD } override fun run(monitor: IProgressMonitor?): IStatus = try { rebuildTask(monitor) Status.OK_STATUS } catch (e: CoreException) { Status(Status.ERROR, Activator.PLUGIN_ID, "Error during build of the project", e) } } ================================================ FILE: kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/compiler/WorkspaceCompilerPropertyPage.kt ================================================ package org.jetbrains.kotlin.preferences.compiler import org.eclipse.core.resources.IncrementalProjectBuilder.FULL_BUILD import org.eclipse.core.resources.ResourcesPlugin import org.eclipse.swt.widgets.Composite import org.eclipse.swt.widgets.Control import org.eclipse.ui.IWorkbench import org.eclipse.ui.IWorkbenchPreferencePage import org.jetbrains.kotlin.core.model.KotlinEnvironment import org.jetbrains.kotlin.core.preferences.KotlinProperties import org.jetbrains.kotlin.preferences.BasePropertyPage import org.jetbrains.kotlin.preferences.views.compilerPropertiesView import org.jetbrains.kotlin.swt.builders.asView class WorkspaceCompilerPropertyPage : BasePropertyPage(), IWorkbenchPreferencePage { override val properties = KotlinProperties.workspaceInstance override fun init(workbench: IWorkbench?) { } override fun createUI(parent: Composite): Control = parent.asView .compilerPropertiesView(properties) { onIsValidChanged = { setValid(it) } } .control override fun afterOk() { RebuildJob { monitor -> KotlinEnvironment.removeAllEnvironments() ResourcesPlugin.getWorkspace().build(FULL_BUILD, monitor) }.schedule() } } ================================================ FILE: kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/style/ProjectCodeStylePropertyPage.kt ================================================ package org.jetbrains.kotlin.preferences.style import org.eclipse.core.resources.IProject import org.eclipse.core.resources.ProjectScope import org.eclipse.swt.widgets.Composite import org.eclipse.swt.widgets.Control import org.eclipse.ui.IWorkbenchPropertyPage import org.jetbrains.kotlin.core.preferences.KotlinCodeStyleProperties import org.jetbrains.kotlin.preferences.BasePropertyPage import org.jetbrains.kotlin.preferences.views.codeStylePropertiesView import org.jetbrains.kotlin.swt.builders.* import org.jetbrains.kotlin.utils.LazyObservable import kotlin.properties.Delegates class ProjectCodeStylePropertyPage : BasePropertyPage(), IWorkbenchPropertyPage { // project must be lazy initialized, because getElement() called during construction of page object returns null val project: IProject by lazy { element.getAdapter(IProject::class.java) } private var overrideFlag by LazyObservable({ properties.globalsOverridden }) { _, _, v -> properties.globalsOverridden = v settingsView.enabled = v } private lateinit var settingsView: View override val properties by lazy { KotlinCodeStyleProperties(ProjectScope(project)) } override fun createUI(parent: Composite): Control = parent.asView.apply { checkbox(::overrideFlag, "Enable project speciffic settings") separator { layout(horizontalGrab = true) } settingsView = codeStylePropertiesView(properties) { enabled = properties.globalsOverridden } }.control } ================================================ FILE: kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/style/WorkspaceCodeStylePropertyPage.kt ================================================ package org.jetbrains.kotlin.preferences.style import org.eclipse.swt.widgets.Composite import org.eclipse.swt.widgets.Control import org.eclipse.ui.IWorkbench import org.eclipse.ui.IWorkbenchPreferencePage import org.jetbrains.kotlin.core.preferences.KotlinCodeStyleProperties import org.jetbrains.kotlin.preferences.BasePropertyPage import org.jetbrains.kotlin.preferences.views.codeStylePropertiesView import org.jetbrains.kotlin.swt.builders.* class WorkspaceCodeStylePropertyPage : BasePropertyPage(), IWorkbenchPreferencePage { override val properties = KotlinCodeStyleProperties.workspaceInstance override fun init(workbench: IWorkbench?) { } override fun createUI(parent: Composite): Control = parent.asView.apply { codeStylePropertiesView(properties) }.control } ================================================ FILE: kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/views/BuildingPropertiesView.kt ================================================ package org.jetbrains.kotlin.preferences.views import org.eclipse.swt.widgets.Composite import org.jetbrains.kotlin.core.preferences.KotlinBuildingProperties import org.jetbrains.kotlin.swt.builders.View import org.jetbrains.kotlin.swt.builders.checkbox import org.jetbrains.kotlin.swt.builders.gridContainer import kotlin.properties.Delegates fun View.buildingPropertiesView( kotlinBuildingProperties: KotlinBuildingProperties, operations: BuildingPropertiesView.() -> Unit = {} ) = BuildingPropertiesView(this, kotlinBuildingProperties) .apply(operations) class BuildingPropertiesView( parent: View, kotlinBuildingProperties: KotlinBuildingProperties ) : View, Validable { override val control: Composite override var isValid: Boolean = true private set(value) { field = value onIsValidChanged(value) } override var onIsValidChanged: (Boolean) -> Unit = {} private var useIncremental by Delegates.observable(kotlinBuildingProperties.useIncremental) { _, _, value -> kotlinBuildingProperties.useIncremental = value } init { control = parent.gridContainer { checkbox(::useIncremental, "Use incremental compiler (experimental)") }.control } } ================================================ FILE: kotlin-eclipse-ui/src/org/jetbrains/kotlin/preferences/views/CompilerPropertiesView.kt ================================================ package org.jetbrains.kotlin.preferences.views import org.eclipse.jface.resource.FontDescriptor import org.eclipse.swt.SWT import org.eclipse.swt.layout.GridLayout import org.eclipse.swt.widgets.* import org.jetbrains.kotlin.config.ApiVersion import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.config.LanguageVersion import org.jetbrains.kotlin.core.preferences.CompilerPlugin import org.jetbrains.kotlin.core.preferences.KotlinProperties import org.jetbrains.kotlin.preferences.compiler.CompilerPluginDialog import org.jetbrains.kotlin.swt.builders.* import org.jetbrains.kotlin.utils.LazyObservable import kotlin.properties.Delegates fun View.compilerPropertiesView( kotlinProperties: KotlinProperties, operations: CompilerPropertiesView.() -> Unit = {} ) = CompilerPropertiesView(this, kotlinProperties) .apply(operations) class CompilerPropertiesView( parent: View, private val kotlinProperties: KotlinProperties ) : View, Validable { override val control: Composite override var isValid: Boolean = true private set(value) { field = value onIsValidChanged(value) } override var onIsValidChanged: (Boolean) -> Unit = {} private var languageVersionProxy: LanguageVersion by LazyObservable( initialValueProvider = { kotlinProperties.languageVersion }, onChange = { _, _, value -> kotlinProperties.languageVersion = value checkApiVersionCorrectness() } ) private var apiVersionProxy: ApiVersion by LazyObservable( initialValueProvider = { kotlinProperties.apiVersion }, onChange = { _, _, value -> kotlinProperties.apiVersion = value checkApiVersionCorrectness() } ) private var jdkHomeProxy: String? by LazyObservable( initialValueProvider = { kotlinProperties.jdkHome }, onChange = { _, oldValue, value -> if (oldValue != value) { kotlinProperties.jdkHome = value jdkHomeTextField.update(value.orEmpty()) } } ) private lateinit var apiVersionErrorLabel: Label private lateinit var jdkHomeTextField: View private var selectedPlugin by Delegates.observable(null) { _, _, value -> val source = value?.source editButton.enabled = source != null removeButton.enabled = source != null && source != CompilerPluginSource.Inherited removeButton.label = if (source == CompilerPluginSource.InheritedOverridden) "Restore" else "Remove" } private lateinit var editButton: View