diff --git a/detekt_baseline.xml b/detekt_baseline.xml index 8988b113f..772c47aac 100644 --- a/detekt_baseline.xml +++ b/detekt_baseline.xml @@ -3,98 +3,29 @@ ComplexCondition:SemanticTokens.kt$element is KtVariableDeclaration && (!element.isVar || element.hasModifier(KtTokens.CONST_KEYWORD)) || element is KtParameter - CyclomaticComplexMethod:Completions.kt$private fun elementCompletions(file: CompiledFile, cursor: Int, surroundingElement: KtElement): Sequence<DeclarationDescriptor> CyclomaticComplexMethod:Completions.kt$private fun indexCompletionItems(file: CompiledFile, cursor: Int, element: KtElement?, index: SymbolIndex, partial: String): Sequence<CompletionItem> - CyclomaticComplexMethod:GoToDefinition.kt$fun goToDefinition( file: CompiledFile, cursor: Int, classContentProvider: ClassContentProvider, tempDir: TemporaryDirectory, config: ExternalSourcesConfiguration, cp: CompilerClassPath ): Location? - CyclomaticComplexMethod:KotlinWorkspaceService.kt$KotlinWorkspaceService$override fun didChangeConfiguration(params: DidChangeConfigurationParams) CyclomaticComplexMethod:SemanticTokens.kt$private fun elementToken(element: PsiElement, bindingContext: BindingContext): SemanticToken? CyclomaticComplexMethod:StringUtils.kt$fun stringDistance(candidate: CharSequence, pattern: CharSequence, maxOffset: Int = 4): Int - EmptyCatchBlock:LintTest.kt$LintTest${} - EmptyClassBlock:BigFile.kt$BigFile.Maze${} - EmptyClassBlock:BigFile.kt$BigFile.MyClass${} - EmptyClassBlock:Constructor.kt$SomeConstructor${ } - EmptyClassBlock:Enum.kt$TokenType.Companion${ } - EmptyClassBlock:OuterDotInner.kt$MyOuterClass.InnerClass${ } - EmptyClassBlock:OverrideMembers.kt$Closed${} - EmptyClassBlock:OverrideMembers.kt$MyPrintable${} - EmptyClassBlock:OverrideMembers.kt$MyThread${} - EmptyClassBlock:SomeOtherClass.kt$SomeOtherClass${ } - EmptyClassBlock:SomeSubclass.kt$SomeSubclass${ } - EmptyClassBlock:Types.kt$Types.SomeInnerObject${ } - EmptyClassBlock:When.kt$SealedClass.Test${} - EmptyClassBlock:samefile.kt$MyClass${ } - EmptyClassBlock:samefile.kt$MyImplClass${} - EmptyClassBlock:samefile.kt$NullClass${} - EmptyClassBlock:samefile.kt$PrintableClass${} - EmptyClassBlock:standardlib.kt$MyComperable${} - EmptyClassBlock:standardlib.kt$MyList${} - EmptyClassBlock:standardlib.kt$MyThread${} - EmptyDefaultConstructor:BigFile.kt$BigFile.A$() - EmptyDefaultConstructor:BigFile.kt$BigFile.B$() - EmptyDefaultConstructor:BigFile.kt$BigFile.Body$() - EmptyDefaultConstructor:BigFile.kt$BigFile.Delegate$() - EmptyDefaultConstructor:BigFile.kt$BigFile.H1$() - EmptyDefaultConstructor:BigFile.kt$BigFile.HTML$() - EmptyDefaultConstructor:BigFile.kt$BigFile.Head$() - EmptyDefaultConstructor:BigFile.kt$BigFile.LI$() - EmptyDefaultConstructor:BigFile.kt$BigFile.MyClass$() - EmptyDefaultConstructor:BigFile.kt$BigFile.P$() - EmptyDefaultConstructor:BigFile.kt$BigFile.Title$() - EmptyDefaultConstructor:BigFile.kt$BigFile.UL$() - EmptyDefaultConstructor:Types.kt$Types.SomeInnerClass$() - EmptyForBlock:ReferenceCollectionish.kt${ } - EmptyFunctionBlock:BackquotedFunction.kt${ } - EmptyFunctionBlock:DocumentSymbols.kt$DocumentSymbols${ } - EmptyFunctionBlock:FillEmptyBody.kt$Caller${ } - EmptyFunctionBlock:GoFrom.kt$GoFrom${ } - EmptyFunctionBlock:GoTo.kt$GoTo${ } - EmptyFunctionBlock:JvmNameAnnotation.kt${ } - EmptyFunctionBlock:KotlinLanguageServer.kt$KotlinLanguageServer${} + EmptyClassBlock:KotlinLSException.kt$KotlinLSException${ } EmptyFunctionBlock:Logger.kt$JULRedirector${} EmptyFunctionBlock:LoggingMessageCollector.kt$LoggingMessageCollector${} - EmptyFunctionBlock:ObjectReference.kt$AnObject${ } - EmptyFunctionBlock:ReferenceGetterSetter.kt$ReferenceGetterSetter${ } - EmptyFunctionBlock:ReferenceTo.kt$ReferenceTo${ } - EmptyFunctionBlock:ResolveToFile.kt$ResolveToFile${ } - EmptyFunctionBlock:SignatureHelp.kt$Target${ } - EmptyFunctionBlock:SomeSubclass.kt$YetAnotherSubclass${ } - EmptyFunctionBlock:Statics.kt$MyClass.Companion${ } - EmptyFunctionBlock:Statics.kt$MyObject${ } - EmptyFunctionBlock:TrailingLambda.kt${} - EmptyFunctionBlock:Visibility.kt$Visibility${ } - EmptyFunctionBlock:Visibility.kt$Visibility.Companion${ } - EmptyFunctionBlock:Visibility.kt$VisibilitySuper${ } - EmptyFunctionBlock:Visibility.kt$VisibilitySuper.Companion${ } - EmptyFunctionBlock:Visibility.kt${ } - EmptyFunctionBlock:samefile.kt$OtherPrintableClass${} - EmptySecondaryConstructor:DocumentSymbols.kt$DocumentSymbols${ } - EmptySecondaryConstructor:KotlinLSException.kt$KotlinLSException${} - EmptySecondaryConstructor:OtherFileSymbols.kt$OtherFileSymbols${ } - EmptySecondaryConstructor:ReferenceConstructor.kt$ReferenceConstructor${ } - EmptySecondaryConstructor:SourceExclusions.kt$SourceExclusions${} - EqualsAlwaysReturnsTrueOrFalse:OverrideMembers.kt$CompletePrintable$override fun equals(other: Any?): Boolean - EqualsWithHashCodeExist:ReferenceOperator.kt$ReferenceEquals - EqualsWithHashCodeExist:ReferenceOperator.kt$ReferenceOperator - EqualsWithHashCodeExist:ReferenceOperatorUsingName.kt$ReferenceOperatorUsingName ExplicitItLambdaParameter:Hovers.kt${ i, it -> val ret: String if (i == 0) ret = it.substring(it.indexOf("/**") + 3) // get rid of the start comment characters else if (i == split.size - 1) ret = it.substring(it.indexOf("*/") + 2) // get rid of the end comment characters else ret = it.substring(it.indexOf('*') + 1) // get rid of any leading * ret } ExplicitItLambdaParameter:RenderCompletionItem.kt${ it -> it } ForbiddenComment:AddMissingImportsQuickFix.kt$AddMissingImportsQuickFix$// TODO: Visibility checker should be less liberal ForbiddenComment:BackupClassPathResolver.kt$// TODO: Resolve the gradleCaches dynamically instead of hardcoding this path + ForbiddenComment:CompilationEnvironment.kt$CompilationEnvironment$// TODO: KotlinScriptDefinition will soon be deprecated, use + ForbiddenComment:CompilationEnvironment.kt$CompilationEnvironment$// TODO: Use ScriptDefinition.FromLegacyTemplate directly if possible ForbiddenComment:CompiledFile.kt$CompiledFile$* Looks for a reference expression at the given cursor. * This is currently used by many features in the language server. * Unfortunately, it fails to find declarations for JDK symbols. * [referenceExpressionAtPoint] provides an alternative implementation that can find JDK symbols. * It cannot, however, replace this method at the moment. * TODO: Investigate why this method doesn't find JDK symbols. - ForbiddenComment:Compiler.kt$CompilationEnvironment$// TODO: KotlinScriptDefinition will soon be deprecated, use - ForbiddenComment:Compiler.kt$CompilationEnvironment$// TODO: Use ScriptDefinition.FromLegacyTemplate directly if possible ForbiddenComment:Compiler.kt$Compiler$// TODO: Lock at file-level ForbiddenComment:CompilerClassPath.kt$CompilerClassPath$// TODO: Fetch class path and build script class path concurrently (and asynchronously) ForbiddenComment:Completions.kt$// TODO: CRLF? ForbiddenComment:Completions.kt$// TODO: Deal with alias imports ForbiddenComment:Completions.kt$// TODO: Visibility checker should be less liberal - ForbiddenComment:Home.kt$// TODO: try and figure out if mavenHome is in non-default position (requires finding and parsing settings.xml) ForbiddenComment:Imports.kt$// TODO: Lexicographic insertion ForbiddenComment:JavaElementConverter.kt$JavaElementConverter$// TODO: Break labels ForbiddenComment:JavaElementConverter.kt$JavaElementConverter$// TODO: Nullability ForbiddenComment:JavaElementConverter.kt$JavaElementConverter$// TODO: Type parameters, annotations, modifiers, ... ForbiddenComment:JavaElementConverter.kt$JavaElementConverter$// TODO: Varargs, ... - ForbiddenComment:JavaToKotlinTest.kt$JavaToKotlinTest$// TODO: Seems to throw the same exception as ForbiddenComment:JdkSourceArchiveProvider.kt$JdkSourceArchiveProvider$* Checks if the given path is inside the JDK. If it is, we return the corresponding source zip. * Note that this method currently doesn't take into the account the JDK version, which means JDK source code * is only available for JDK 9+ builds. * TODO: improve this resolution logic to work for older JDK versions as well. ForbiddenComment:KotlinTextDocumentService.kt$KotlinTextDocumentService$// TODO: Investigate when to recompile ForbiddenComment:OverrideMembers.kt$// TODO: any way can repeat less code between this and the getAbstractMembersStubs in the ImplementAbstractMembersQuickfix? @@ -103,45 +34,16 @@ ForbiddenComment:OverrideMembers.kt$// TODO: look into this ForbiddenComment:OverrideMembers.kt$// TODO: see where this should ideally be placed ForbiddenComment:SemanticTokens.kt$// TODO: Ideally we would like to cut-off subtrees outside our range, but this doesn't quite seem to work - ForbiddenComment:SimpleScriptTest.kt$SimpleScriptTest$// TODO: - ForbiddenComment:SimpleScriptTest.kt$SimpleScriptTest$// TODO: Test a script using the language server instead ForbiddenComment:SourceExclusions.kt$SourceExclusions$// TODO: Read exclusions from gitignore/settings.json/... instead of - ForbiddenComment:SourcePath.kt$SourcePath$// TODO: Investigate the possibility of compiling all files at once, instead of iterating here + ForbiddenComment:SourcePath.kt$SourcePath$// TODO: Investigate the possibility of compiling all files at once, instead of iterating ForbiddenComment:SourcePath.kt$SourcePath.SourceFile$// TODO: Create PsiFile using the stored language instead ForbiddenComment:SourcePath.kt$SourcePath.SourceFile$// TODO: Use language?.associatedFileType?.defaultExtension again ForbiddenComment:Symbol.kt$Symbol$// TODO: Store location (e.g. using a URI) ForbiddenComment:SymbolIndex.kt$SymbolIndex$// TODO: Extension completion currently only works if the receiver matches exactly, - ForbiddenComment:build.gradle.kts$// TODO: Currently not possible, see https://github.com/gradle/gradle/issues/9830 - FunctionNaming:Accessors46nwrg1rs44ofdqpi7vyy3pfc.kt$internal fun org.gradle.api.artifacts.dsl.RepositoryHandler.`ext`(configure: Action<org.gradle.api.plugins.ExtraPropertiesExtension>): Unit - FunctionNaming:Accessors8lcri9ibgd9oj8dt3t8z8nvfx.kt$internal fun org.gradle.api.artifacts.dsl.DependencyHandler.`ext`(configure: Action<org.gradle.api.plugins.ExtraPropertiesExtension>): Unit - FunctionNaming:Accessorsasa455whv8s4bk3c97fzgde0p.kt$internal fun org.gradle.api.publish.PublishingExtension.`ext`(configure: Action<org.gradle.api.plugins.ExtraPropertiesExtension>): Unit - FunctionNaming:Accessorsblypoh2ruc9u3bx9djsfqsntg.kt$internal fun org.gradle.api.Project.`ext`(configure: Action<org.gradle.api.plugins.ExtraPropertiesExtension>): Unit - FunctionNaming:Accessorscchdiujech8u294vwhihsq7gh.kt$internal fun org.gradle.api.Project.`publishing`(configure: Action<org.gradle.api.publish.PublishingExtension>): Unit FunctionOnlyReturningConstant:Example.kt$fun example() - FunctionOnlyReturningConstant:FunctionScope.kt$FunctionScope$private fun aClassFun() - FunctionOnlyReturningConstant:FunctionScope.kt$FunctionScope.Companion$private fun aCompanionFun() - FunctionOnlyReturningConstant:InstanceMember.kt$SomeClass$fun instanceFee() - FunctionOnlyReturningConstant:InstanceMember.kt$SomeClass$fun instanceFoo() - FunctionOnlyReturningConstant:InstanceMember.kt$SomeClass$private fun privateInstanceFoo() - FunctionOnlyReturningConstant:InstanceMember.kt$private fun SomeClass.extensionFoo() - FunctionOnlyReturningConstant:LintErrors.kt$LintErrors$fun foo() - FunctionOnlyReturningConstant:Recover.kt$private fun intFunction() - FunctionOnlyReturningConstant:Recover.kt$private fun singleExpressionFunction() - InvalidPackageDeclaration:CompanionObject.kt$package test.my.companion - InvalidPackageDeclaration:DeclSite.kt$package declsite - InvalidPackageDeclaration:JvmNameAnnotation.kt$package com.mypackage.name - InvalidPackageDeclaration:NoMain.kt$package no.main.found.hopefully - InvalidPackageDeclaration:Simple.kt$package test - InvalidPackageDeclaration:Simple.kt$package test.mypackage - InvalidPackageDeclaration:UsageSite.kt$package declsite - InvalidPackageDeclaration:samefile.kt$package test.kotlin.lsp - InvalidPackageDeclaration:standardlib.kt$package test.kotlin.lsp - LongMethod:Compiler.kt$CompilationEnvironment.<no name provided>.<no name provided>$override fun resolve(scriptContents: ScriptContents, environment: Environment) - LongMethod:Completions.kt$private fun elementCompletions(file: CompiledFile, cursor: Int, surroundingElement: KtElement): Sequence<DeclarationDescriptor> + LongMethod:CompilationEnvironment.kt$CompilationEnvironment.<no name provided>.<no name provided>$override fun resolve( scriptContents: ScriptContents, environment: Environment ) LongMethod:SemanticTokens.kt$private fun elementToken(element: PsiElement, bindingContext: BindingContext): SemanticToken? - LongParameterList:CompiledFile.kt$CompiledFile$( val content: String, val parse: KtFile, val compile: BindingContext, val module: ModuleDescriptor, val sourcePath: Collection<KtFile>, val classPath: CompilerClassPath, val isScript: Boolean = false, val kind: CompilationKind = CompilationKind.DEFAULT ) - LongParameterList:GoToDefinition.kt$( file: CompiledFile, cursor: Int, classContentProvider: ClassContentProvider, tempDir: TemporaryDirectory, config: ExternalSourcesConfiguration, cp: CompilerClassPath ) - LongParameterList:LanguageServerTestFixture.kt$LanguageServerTestFixture$(relativePath: String, startLine: Int, startColumn: Int, endLine: Int, endColumn: Int, diagnostics: List<Diagnostic>, only: List<String>) + LongParameterList:CompiledFile.kt$CompiledFile$( val content: String, val parse: KtFile, val compile: BindingContext, val module: ModuleDescriptor, private val sourcePath: Collection<KtFile>, private val classPath: CompilerClassPath, private val isScript: Boolean = false, val kind: CompilationType = CompilationType.DEFAULT ) LongParameterList:SourcePath.kt$SourcePath.SourceFile$( val uri: URI, var content: String, val path: Path? = uri.filePath, var parsed: KtFile? = null, var compiledFile: KtFile? = null, var compiledContext: BindingContext? = null, var module: ModuleDescriptor? = null, val language: Language? = null, val isTemporary: Boolean = false, // A temporary source file will not be returned by .all() var lastSavedFile: KtFile? = null, ) LoopWithTooManyJumpStatements:StringUtils.kt$for (i in 0 until maxOffset) { when { (iCandidate + i) < candidateLength -> { if (candidate[iCandidate + i] == pattern[iPattern]) { iCandidate += i localCommonSubstring++ break@searchWindow } } (iPattern + i) < patternLength -> { if (candidate[iCandidate] == pattern[iPattern + i]) { iPattern += i localCommonSubstring++ break@searchWindow } } else -> break@searchWindow } } MagicNumber:BackupClassPathResolver.kt$3 @@ -149,9 +51,7 @@ MagicNumber:Compiler.kt$3 MagicNumber:Compiler.kt$5 MagicNumber:CompilerClassPath.kt$5 - MagicNumber:Formatter.kt$4 MagicNumber:Hovers.kt$3 - MagicNumber:KotlinLanguageServer.kt$KotlinLanguageServer$100 MagicNumber:Logger.kt$LogLevel.ALL$100 MagicNumber:Logger.kt$LogLevel.DEEP_TRACE$3 MagicNumber:Logger.kt$LogLevel.NONE$100 @@ -162,6 +62,7 @@ MagicNumber:MavenClassPathResolver.kt$5 MagicNumber:MavenClassPathResolver.kt$6 MagicNumber:MavenClassPathResolver.kt$MavenClassPathResolver$5 + MagicNumber:Server.kt$Server$100 MagicNumber:Symbol.kt$Symbol.Kind.CONSTRUCTOR$7 MagicNumber:Symbol.kt$Symbol.Kind.ENUM$5 MagicNumber:Symbol.kt$Symbol.Kind.ENUM_MEMBER$6 @@ -176,89 +77,23 @@ MagicNumber:WithStdlibResolver.kt$StdLibItem.Companion$3 MagicNumber:WithStdlibResolver.kt$StdLibItem.Companion$4 MagicNumber:WithStdlibResolver.kt$StdLibItem.Companion$5 - MatchingDeclarationName:Enum.kt$TokenType - MatchingDeclarationName:ImportsTest.kt$ImportTextEditTest : SingleFileTestFixture MatchingDeclarationName:Main.kt$Args - MatchingDeclarationName:Spaces.kt$Test - MatchingDeclarationName:When.kt$SealedClass - MayBeConst:CompanionObject.kt$val SOME_GLOBAL_CONSTANT = 42 - MayBeConst:DeclSite.kt$val myvar = 2 - MayBeConst:DocumentHighlight.kt$val globalval = 23 - MayBeConst:FunctionScope.kt$FunctionScope.Companion$private val aCompanionVal = 1 - MayBeConst:JvmNameAnnotation.kt$val MY_CONSTANT = 1 - MayBeConst:OtherFile.kt$val somevalinotherfile = 42 - MayBeConst:Simple.kt$val something = 1 - MemberNameEqualsClassName:ReferenceGetSetValue.kt$Main$private fun main() NestedBlockDepth:Completions.kt$private fun completeMembers(file: CompiledFile, cursor: Int, receiverExpr: KtExpression, unwrapNullable: Boolean = false): Sequence<DeclarationDescriptor> - NestedBlockDepth:GoToDefinition.kt$fun goToDefinition( file: CompiledFile, cursor: Int, classContentProvider: ClassContentProvider, tempDir: TemporaryDirectory, config: ExternalSourcesConfiguration, cp: CompilerClassPath ): Location? - NestedBlockDepth:KotlinWorkspaceService.kt$KotlinWorkspaceService$override fun didChangeConfiguration(params: DidChangeConfigurationParams) NestedBlockDepth:KotlinWorkspaceService.kt$KotlinWorkspaceService$override fun didChangeWatchedFiles(params: DidChangeWatchedFilesParams) - NestedBlockDepth:LanguageServerTestFixture.kt$LanguageServerTestFixture$private fun createLanguageServer(): KotlinLanguageServer NestedBlockDepth:OverrideMembers.kt$private fun parametersMatch( function: KtNamedFunction, functionDescriptor: FunctionDescriptor ): Boolean NestedBlockDepth:SourcePath.kt$SourcePath$fun save(uri: URI) NestedBlockDepth:StringUtils.kt$fun stringDistance(candidate: CharSequence, pattern: CharSequence, maxOffset: Int = 4): Int - NewLineAtEndOfFile:BackquotedFunction.kt$.BackquotedFunction.kt - NewLineAtEndOfFile:BigFile.kt$.BigFile.kt - NewLineAtEndOfFile:CompiledFileExample.kt$.CompiledFileExample.kt - NewLineAtEndOfFile:Constructor.kt$.Constructor.kt - NewLineAtEndOfFile:DocumentSymbols.kt$.DocumentSymbols.kt - NewLineAtEndOfFile:DoubleDot.kt$.DoubleDot.kt - NewLineAtEndOfFile:EditCall.kt$.EditCall.kt NewLineAtEndOfFile:Example.kt$.Example.kt - NewLineAtEndOfFile:ExampleScript.kts$.ExampleScript.kts - NewLineAtEndOfFile:FileToEdit.kt$.FileToEdit.kt - NewLineAtEndOfFile:FillEmptyBody.kt$.FillEmptyBody.kt - NewLineAtEndOfFile:FindDoc.kt$org.javacs.kt.docs.FindDoc.kt - NewLineAtEndOfFile:FunctionReference.kt$.FunctionReference.kt - NewLineAtEndOfFile:FunctionScope.kt$.FunctionScope.kt - NewLineAtEndOfFile:GoFrom.kt$.GoFrom.kt - NewLineAtEndOfFile:GoTo.kt$.GoTo.kt - NewLineAtEndOfFile:InstanceMembersJava.kt$.InstanceMembersJava.kt - NewLineAtEndOfFile:LintErrors.kt$.LintErrors.kt - NewLineAtEndOfFile:Literals.kt$.Literals.kt - NewLineAtEndOfFile:MiddleOfFunction.kt$.MiddleOfFunction.kt - NewLineAtEndOfFile:ObjectReference.kt$.ObjectReference.kt - NewLineAtEndOfFile:OtherFileSymbols.kt$.OtherFileSymbols.kt - NewLineAtEndOfFile:OuterDotInner.kt$.OuterDotInner.kt - NewLineAtEndOfFile:QuestionDot.kt$.QuestionDot.kt - NewLineAtEndOfFile:Recover.kt$.Recover.kt - NewLineAtEndOfFile:ReferenceCollectionish.kt$.ReferenceCollectionish.kt - NewLineAtEndOfFile:ReferenceComponents.kt$.ReferenceComponents.kt - NewLineAtEndOfFile:ReferenceFrom.kt$.ReferenceFrom.kt - NewLineAtEndOfFile:ReferenceGetSetValue.kt$.ReferenceGetSetValue.kt - NewLineAtEndOfFile:ReferenceGetterSetter.kt$.ReferenceGetterSetter.kt - NewLineAtEndOfFile:ReferenceInvoke.kt$.ReferenceInvoke.kt - NewLineAtEndOfFile:ReferenceOperator.kt$.ReferenceOperator.kt - NewLineAtEndOfFile:ReferenceOperatorUsingName.kt$.ReferenceOperatorUsingName.kt - NewLineAtEndOfFile:ReferenceTo.kt$.ReferenceTo.kt - NewLineAtEndOfFile:ReferencesBigFile.kt$.ReferencesBigFile.kt - NewLineAtEndOfFile:ResolveFromFile.kt$.ResolveFromFile.kt - NewLineAtEndOfFile:ResolveToFile.kt$.ResolveToFile.kt - NewLineAtEndOfFile:SemanticTokens.kt$.SemanticTokens.kt - NewLineAtEndOfFile:SignatureHelp.kt$.SignatureHelp.kt - NewLineAtEndOfFile:Statics.kt$.Statics.kt - NewLineAtEndOfFile:Types.kt$.Types.kt - NewLineAtEndOfFile:configure-publishing.gradle.kts$.configure-publishing.gradle.kts - PackageNaming:Accessors46nwrg1rs44ofdqpi7vyy3pfc.kt$package gradle.kotlin.dsl.accessors._b7719bb009bf77985775c5b9fa4e40d9 - PackageNaming:Accessors6xcmy081jxud3rx4r453mbm9f.kt$package gradle.kotlin.dsl.accessors._b7719bb009bf77985775c5b9fa4e40d9 - PackageNaming:Accessors8lcri9ibgd9oj8dt3t8z8nvfx.kt$package gradle.kotlin.dsl.accessors._b7719bb009bf77985775c5b9fa4e40d9 - PackageNaming:Accessorsasa455whv8s4bk3c97fzgde0p.kt$package gradle.kotlin.dsl.accessors._b7719bb009bf77985775c5b9fa4e40d9 - PackageNaming:Accessorsb13nju9doius8kxwhlptqirtr.kt$package gradle.kotlin.dsl.accessors._b7719bb009bf77985775c5b9fa4e40d9 - PackageNaming:Accessorsblypoh2ruc9u3bx9djsfqsntg.kt$package gradle.kotlin.dsl.accessors._b7719bb009bf77985775c5b9fa4e40d9 - PackageNaming:Accessorscchdiujech8u294vwhihsq7gh.kt$package gradle.kotlin.dsl.accessors._b7719bb009bf77985775c5b9fa4e40d9 - PackageNaming:JavaJSONConverter.kt$package j2k - PackageNaming:PluginSpecBuilders.kt$package gradle.kotlin.dsl.plugins._7df07e7e20c071e0f60c36a84fdf1bc1 - ReturnCount:BigFile.kt$BigFile$fun Maze.addIfFree(i: Int, j: Int, result: MutableList<Point>) ReturnCount:CompiledFile.kt$CompiledFile$fun referenceAtPoint(cursor: Int): Pair<KtExpression, DeclarationDescriptor>? ReturnCount:CompiledFile.kt$CompiledFile$fun typeAtPoint(cursor: Int): KotlinType? ReturnCount:Completions.kt$private fun completeMembers(file: CompiledFile, cursor: Int, receiverExpr: KtExpression, unwrapNullable: Boolean = false): Sequence<DeclarationDescriptor> - ReturnCount:Completions.kt$private fun elementCompletions(file: CompiledFile, cursor: Int, surroundingElement: KtElement): Sequence<DeclarationDescriptor> ReturnCount:Completions.kt$private fun findPartialIdentifier(file: CompiledFile, cursor: Int): String ReturnCount:Completions.kt$private fun implicitMembers(scope: HierarchicalScope): Sequence<DeclarationDescriptor> ReturnCount:Completions.kt$private fun isNotStaticJavaMethod( descriptor: DeclarationDescriptor ): Boolean ReturnCount:Completions.kt$private fun isNotVisible(target: DeclarationDescriptorWithVisibility, from: DeclarationDescriptor): Boolean ReturnCount:Completions.kt$private fun isVisible(file: CompiledFile, cursor: Int): (DeclarationDescriptor) -> Boolean ReturnCount:Completions.kt$private fun subclassParent(target: DeclarationDescriptor, from: DeclarationDescriptor): Boolean + ReturnCount:DefinitionHandler.kt$DefinitionHandler$fun goToDefinition(file: CompiledFile, cursor: Int): Location? ReturnCount:FindDoc.kt$fun findDoc(declaration: DeclarationDescriptorWithSource): KDocTag? ReturnCount:FindReferences.kt$private fun possibleReferences(declaration: DeclarationDescriptor, sp: SourcePath): Set<KtFile> ReturnCount:Hovers.kt$@OptIn(IDEAPluginsCompatibilityAPI::class) private fun renderTypeOf(element: KtExpression, bindingContext: BindingContext): String? @@ -267,28 +102,22 @@ ReturnCount:Position.kt$fun location(declaration: DeclarationDescriptor): Location? ReturnCount:ResolveMain.kt$fun resolveMain(file: CompiledFile): Map<String,Any> ReturnCount:SemanticTokens.kt$private fun elementToken(element: PsiElement, bindingContext: BindingContext): SemanticToken? - ReturnCount:SignatureHelp.kt$private fun activeParameter(call: KtCallExpression, cursor: Int): Int ReturnCount:SignatureHelp.kt$private fun candidates(call: KtCallExpression, file: CompiledFile): List<CallableDescriptor> ReturnCount:SignatureHelp.kt$private fun isCompatibleWith(call: KtCallExpression, candidate: CallableDescriptor): Boolean SpreadOperator:Main.kt$(*argv) - SwallowedException:AsyncExecutor.kt$AsyncExecutor$e: Exception SwallowedException:ClassContentProvider.kt$ClassContentProvider$e: FileNotFoundException - SwallowedException:ConfigurePublishingPlugin.kt$ConfigurePublishingPlugin$e: java.lang.reflect.InvocationTargetException - SwallowedException:LintTest.kt$LintTest$ex: CancellationException SwallowedException:Position.kt$e: NullPointerException SwallowedException:SourceFiles.kt$SourceFiles$e: FileNotFoundException SwallowedException:SourceFiles.kt$SourceFiles$e: IOException SwallowedException:SymbolIndex.kt$SymbolIndex$e: IllegalStateException - TooGenericExceptionCaught:AsyncExecutor.kt$AsyncExecutor$e: Exception TooGenericExceptionCaught:ClassPathResolver.kt$ClassPathResolver$e: Exception - TooGenericExceptionCaught:Compiler.kt$CompilationEnvironment$e: Exception + TooGenericExceptionCaught:CompilationEnvironment.kt$CompilationEnvironment$e: Exception TooGenericExceptionCaught:Completions.kt$e: Exception TooGenericExceptionCaught:DefaultClassPathResolver.kt$e: Exception TooGenericExceptionCaught:Position.kt$e: NullPointerException TooGenericExceptionCaught:SourcePath.kt$SourcePath$ex: Exception TooGenericExceptionCaught:SymbolIndex.kt$SymbolIndex$e: Exception TooGenericExceptionCaught:Utils.kt$e: Exception - TooGenericExceptionThrown:OneFilePerformance.kt$OneFilePerformance$throw RuntimeException("Expected BigFile.max but found " + call) TooGenericExceptionThrown:Position.kt$throw RuntimeException("Reached end of file before reaching char $char") TooGenericExceptionThrown:Position.kt$throw RuntimeException("Reached end of file before reaching line $line") TooGenericExceptionThrown:Position.kt$throw RuntimeException("Reached end of file before reaching offset $offset") @@ -303,257 +132,43 @@ TooManyFunctions:FindReferences.kt$org.javacs.kt.references.FindReferences.kt TooManyFunctions:JavaElementConverter.kt$JavaElementConverter : JavaElementVisitor TooManyFunctions:JavaTypeConverter.kt$JavaTypeConverter : PsiTypeVisitor - TooManyFunctions:KotlinLanguageServer.kt$KotlinLanguageServer : LanguageServerLanguageClientAwareCloseable TooManyFunctions:KotlinTextDocumentService.kt$KotlinTextDocumentService : TextDocumentServiceCloseable TooManyFunctions:Logger.kt$Logger TooManyFunctions:OverrideMembers.kt$org.javacs.kt.overridemembers.OverrideMembers.kt TooManyFunctions:RenderCompletionItem.kt$RenderCompletionItem : DeclarationDescriptorVisitor + TooManyFunctions:Server.kt$Server : LanguageServerLanguageClientAwareCloseable TooManyFunctions:SignatureHelp.kt$org.javacs.kt.signaturehelp.SignatureHelp.kt TooManyFunctions:SourceFiles.kt$SourceFiles TooManyFunctions:SourcePath.kt$SourcePath TooManyFunctions:SourcePath.kt$SourcePath$SourceFile - TooManyFunctions:Utils.kt$org.javacs.kt.util.Utils.kt - TopLevelPropertyNaming:Accessors46nwrg1rs44ofdqpi7vyy3pfc.kt$/** * Retrieves the [ext][org.gradle.api.plugins.ExtraPropertiesExtension] extension. */ internal val org.gradle.api.artifacts.dsl.RepositoryHandler.`ext`: org.gradle.api.plugins.ExtraPropertiesExtension get() = (this as org.gradle.api.plugins.ExtensionAware).extensions.getByName("ext") as org.gradle.api.plugins.ExtraPropertiesExtension - TopLevelPropertyNaming:Accessors6xcmy081jxud3rx4r453mbm9f.kt$/** * Provides the existing [publishToMavenLocal][org.gradle.api.DefaultTask] task. */ internal val TaskContainer.`publishToMavenLocal`: TaskProvider<org.gradle.api.DefaultTask> get() = named<org.gradle.api.DefaultTask>("publishToMavenLocal") - TopLevelPropertyNaming:Accessors8lcri9ibgd9oj8dt3t8z8nvfx.kt$/** * Retrieves the [ext][org.gradle.api.plugins.ExtraPropertiesExtension] extension. */ internal val org.gradle.api.artifacts.dsl.DependencyHandler.`ext`: org.gradle.api.plugins.ExtraPropertiesExtension get() = (this as org.gradle.api.plugins.ExtensionAware).extensions.getByName("ext") as org.gradle.api.plugins.ExtraPropertiesExtension - TopLevelPropertyNaming:Accessorsasa455whv8s4bk3c97fzgde0p.kt$/** * Retrieves the [ext][org.gradle.api.plugins.ExtraPropertiesExtension] extension. */ internal val org.gradle.api.publish.PublishingExtension.`ext`: org.gradle.api.plugins.ExtraPropertiesExtension get() = (this as org.gradle.api.plugins.ExtensionAware).extensions.getByName("ext") as org.gradle.api.plugins.ExtraPropertiesExtension - TopLevelPropertyNaming:Accessorsb13nju9doius8kxwhlptqirtr.kt$/** * Provides the existing [publish][org.gradle.api.DefaultTask] task. */ internal val TaskContainer.`publish`: TaskProvider<org.gradle.api.DefaultTask> get() = named<org.gradle.api.DefaultTask>("publish") - TopLevelPropertyNaming:Accessorsblypoh2ruc9u3bx9djsfqsntg.kt$/** * Retrieves the [ext][org.gradle.api.plugins.ExtraPropertiesExtension] extension. */ internal val org.gradle.api.Project.`ext`: org.gradle.api.plugins.ExtraPropertiesExtension get() = (this as org.gradle.api.plugins.ExtensionAware).extensions.getByName("ext") as org.gradle.api.plugins.ExtraPropertiesExtension - TopLevelPropertyNaming:Accessorscchdiujech8u294vwhihsq7gh.kt$/** * Retrieves the [publishing][org.gradle.api.publish.PublishingExtension] extension. */ internal val org.gradle.api.Project.`publishing`: org.gradle.api.publish.PublishingExtension get() = (this as org.gradle.api.plugins.ExtensionAware).extensions.getByName("publishing") as org.gradle.api.publish.PublishingExtension - TopLevelPropertyNaming:GoToProperties.kt$const val globalNumber: Int = 2 - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * Plugin ids starting with `org.gradle`. */ internal val `OrgPluginGroup`.`gradle`: `OrgGradlePluginGroup` get() = `OrgGradlePluginGroup`(plugins) - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * Plugin ids starting with `org`. */ internal val `PluginDependenciesSpec`.`org`: `OrgPluginGroup` get() = `OrgPluginGroup`(this) - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.antlr` plugin implemented by [org.gradle.api.plugins.antlr.AntlrPlugin]. */ internal val `OrgGradlePluginGroup`.`antlr`: PluginDependencySpec get() = plugins.id("org.gradle.antlr") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.application` plugin implemented by [org.gradle.api.plugins.ApplicationPlugin]. */ internal val `OrgGradlePluginGroup`.`application`: PluginDependencySpec get() = plugins.id("org.gradle.application") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.assembler-lang` plugin implemented by [org.gradle.language.assembler.plugins.AssemblerLangPlugin]. */ internal val `OrgGradlePluginGroup`.`assembler-lang`: PluginDependencySpec get() = plugins.id("org.gradle.assembler-lang") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.assembler` plugin implemented by [org.gradle.language.assembler.plugins.AssemblerPlugin]. */ internal val `OrgGradlePluginGroup`.`assembler`: PluginDependencySpec get() = plugins.id("org.gradle.assembler") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.base` plugin implemented by [org.gradle.api.plugins.BasePlugin]. */ internal val `OrgGradlePluginGroup`.`base`: PluginDependencySpec get() = plugins.id("org.gradle.base") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.binary-base` plugin implemented by [org.gradle.platform.base.plugins.BinaryBasePlugin]. */ internal val `OrgGradlePluginGroup`.`binary-base`: PluginDependencySpec get() = plugins.id("org.gradle.binary-base") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.build-dashboard` plugin implemented by [org.gradle.api.reporting.plugins.BuildDashboardPlugin]. */ internal val `OrgGradlePluginGroup`.`build-dashboard`: PluginDependencySpec get() = plugins.id("org.gradle.build-dashboard") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.build-init` plugin implemented by [org.gradle.buildinit.plugins.BuildInitPlugin]. */ internal val `OrgGradlePluginGroup`.`build-init`: PluginDependencySpec get() = plugins.id("org.gradle.build-init") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.c-lang` plugin implemented by [org.gradle.language.c.plugins.CLangPlugin]. */ internal val `OrgGradlePluginGroup`.`c-lang`: PluginDependencySpec get() = plugins.id("org.gradle.c-lang") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.c` plugin implemented by [org.gradle.language.c.plugins.CPlugin]. */ internal val `OrgGradlePluginGroup`.`c`: PluginDependencySpec get() = plugins.id("org.gradle.c") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.checkstyle` plugin implemented by [org.gradle.api.plugins.quality.CheckstylePlugin]. */ internal val `OrgGradlePluginGroup`.`checkstyle`: PluginDependencySpec get() = plugins.id("org.gradle.checkstyle") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.clang-compiler` plugin implemented by [org.gradle.nativeplatform.toolchain.plugins.ClangCompilerPlugin]. */ internal val `OrgGradlePluginGroup`.`clang-compiler`: PluginDependencySpec get() = plugins.id("org.gradle.clang-compiler") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.codenarc` plugin implemented by [org.gradle.api.plugins.quality.CodeNarcPlugin]. */ internal val `OrgGradlePluginGroup`.`codenarc`: PluginDependencySpec get() = plugins.id("org.gradle.codenarc") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.component-base` plugin implemented by [org.gradle.platform.base.plugins.ComponentBasePlugin]. */ internal val `OrgGradlePluginGroup`.`component-base`: PluginDependencySpec get() = plugins.id("org.gradle.component-base") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.component-model-base` plugin implemented by [org.gradle.language.base.plugins.ComponentModelBasePlugin]. */ internal val `OrgGradlePluginGroup`.`component-model-base`: PluginDependencySpec get() = plugins.id("org.gradle.component-model-base") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.cpp-application` plugin implemented by [org.gradle.language.cpp.plugins.CppApplicationPlugin]. */ internal val `OrgGradlePluginGroup`.`cpp-application`: PluginDependencySpec get() = plugins.id("org.gradle.cpp-application") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.cpp-lang` plugin implemented by [org.gradle.language.cpp.plugins.CppLangPlugin]. */ internal val `OrgGradlePluginGroup`.`cpp-lang`: PluginDependencySpec get() = plugins.id("org.gradle.cpp-lang") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.cpp-library` plugin implemented by [org.gradle.language.cpp.plugins.CppLibraryPlugin]. */ internal val `OrgGradlePluginGroup`.`cpp-library`: PluginDependencySpec get() = plugins.id("org.gradle.cpp-library") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.cpp-unit-test` plugin implemented by [org.gradle.nativeplatform.test.cpp.plugins.CppUnitTestPlugin]. */ internal val `OrgGradlePluginGroup`.`cpp-unit-test`: PluginDependencySpec get() = plugins.id("org.gradle.cpp-unit-test") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.cpp` plugin implemented by [org.gradle.language.cpp.plugins.CppPlugin]. */ internal val `OrgGradlePluginGroup`.`cpp`: PluginDependencySpec get() = plugins.id("org.gradle.cpp") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.cunit-test-suite` plugin implemented by [org.gradle.nativeplatform.test.cunit.plugins.CUnitPlugin]. */ internal val `OrgGradlePluginGroup`.`cunit-test-suite`: PluginDependencySpec get() = plugins.id("org.gradle.cunit-test-suite") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.cunit` plugin implemented by [org.gradle.nativeplatform.test.cunit.plugins.CUnitConventionPlugin]. */ internal val `OrgGradlePluginGroup`.`cunit`: PluginDependencySpec get() = plugins.id("org.gradle.cunit") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.distribution` plugin implemented by [org.gradle.api.distribution.plugins.DistributionPlugin]. */ internal val `OrgGradlePluginGroup`.`distribution`: PluginDependencySpec get() = plugins.id("org.gradle.distribution") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.ear` plugin implemented by [org.gradle.plugins.ear.EarPlugin]. */ internal val `OrgGradlePluginGroup`.`ear`: PluginDependencySpec get() = plugins.id("org.gradle.ear") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.eclipse-wtp` plugin implemented by [org.gradle.plugins.ide.eclipse.EclipseWtpPlugin]. */ internal val `OrgGradlePluginGroup`.`eclipse-wtp`: PluginDependencySpec get() = plugins.id("org.gradle.eclipse-wtp") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.eclipse` plugin implemented by [org.gradle.plugins.ide.eclipse.EclipsePlugin]. */ internal val `OrgGradlePluginGroup`.`eclipse`: PluginDependencySpec get() = plugins.id("org.gradle.eclipse") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.gcc-compiler` plugin implemented by [org.gradle.nativeplatform.toolchain.plugins.GccCompilerPlugin]. */ internal val `OrgGradlePluginGroup`.`gcc-compiler`: PluginDependencySpec get() = plugins.id("org.gradle.gcc-compiler") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.google-test-test-suite` plugin implemented by [org.gradle.nativeplatform.test.googletest.plugins.GoogleTestPlugin]. */ internal val `OrgGradlePluginGroup`.`google-test-test-suite`: PluginDependencySpec get() = plugins.id("org.gradle.google-test-test-suite") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.google-test` plugin implemented by [org.gradle.nativeplatform.test.googletest.plugins.GoogleTestConventionPlugin]. */ internal val `OrgGradlePluginGroup`.`google-test`: PluginDependencySpec get() = plugins.id("org.gradle.google-test") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.groovy-base` plugin implemented by [org.gradle.api.plugins.GroovyBasePlugin]. */ internal val `OrgGradlePluginGroup`.`groovy-base`: PluginDependencySpec get() = plugins.id("org.gradle.groovy-base") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.groovy-gradle-plugin` plugin implemented by [org.gradle.plugin.devel.internal.precompiled.PrecompiledGroovyPluginsPlugin]. */ internal val `OrgGradlePluginGroup`.`groovy-gradle-plugin`: PluginDependencySpec get() = plugins.id("org.gradle.groovy-gradle-plugin") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.groovy` plugin implemented by [org.gradle.api.plugins.GroovyPlugin]. */ internal val `OrgGradlePluginGroup`.`groovy`: PluginDependencySpec get() = plugins.id("org.gradle.groovy") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.help-tasks` plugin implemented by [org.gradle.api.plugins.HelpTasksPlugin]. */ internal val `OrgGradlePluginGroup`.`help-tasks`: PluginDependencySpec get() = plugins.id("org.gradle.help-tasks") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.idea` plugin implemented by [org.gradle.plugins.ide.idea.IdeaPlugin]. */ internal val `OrgGradlePluginGroup`.`idea`: PluginDependencySpec get() = plugins.id("org.gradle.idea") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.ivy-publish` plugin implemented by [org.gradle.api.publish.ivy.plugins.IvyPublishPlugin]. */ internal val `OrgGradlePluginGroup`.`ivy-publish`: PluginDependencySpec get() = plugins.id("org.gradle.ivy-publish") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.jacoco-report-aggregation` plugin implemented by [org.gradle.testing.jacoco.plugins.JacocoReportAggregationPlugin]. */ internal val `OrgGradlePluginGroup`.`jacoco-report-aggregation`: PluginDependencySpec get() = plugins.id("org.gradle.jacoco-report-aggregation") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.jacoco` plugin implemented by [org.gradle.testing.jacoco.plugins.JacocoPlugin]. */ internal val `OrgGradlePluginGroup`.`jacoco`: PluginDependencySpec get() = plugins.id("org.gradle.jacoco") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.java-base` plugin implemented by [org.gradle.api.plugins.JavaBasePlugin]. */ internal val `OrgGradlePluginGroup`.`java-base`: PluginDependencySpec get() = plugins.id("org.gradle.java-base") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.java-gradle-plugin` plugin implemented by [org.gradle.plugin.devel.plugins.JavaGradlePluginPlugin]. */ internal val `OrgGradlePluginGroup`.`java-gradle-plugin`: PluginDependencySpec get() = plugins.id("org.gradle.java-gradle-plugin") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.java-library-distribution` plugin implemented by [org.gradle.api.plugins.JavaLibraryDistributionPlugin]. */ internal val `OrgGradlePluginGroup`.`java-library-distribution`: PluginDependencySpec get() = plugins.id("org.gradle.java-library-distribution") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.java-library` plugin implemented by [org.gradle.api.plugins.JavaLibraryPlugin]. */ internal val `OrgGradlePluginGroup`.`java-library`: PluginDependencySpec get() = plugins.id("org.gradle.java-library") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.java-platform` plugin implemented by [org.gradle.api.plugins.JavaPlatformPlugin]. */ internal val `OrgGradlePluginGroup`.`java-platform`: PluginDependencySpec get() = plugins.id("org.gradle.java-platform") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.java-test-fixtures` plugin implemented by [org.gradle.api.plugins.JavaTestFixturesPlugin]. */ internal val `OrgGradlePluginGroup`.`java-test-fixtures`: PluginDependencySpec get() = plugins.id("org.gradle.java-test-fixtures") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.java` plugin implemented by [org.gradle.api.plugins.JavaPlugin]. */ internal val `OrgGradlePluginGroup`.`java`: PluginDependencySpec get() = plugins.id("org.gradle.java") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.jvm-ecosystem` plugin implemented by [org.gradle.api.plugins.JvmEcosystemPlugin]. */ internal val `OrgGradlePluginGroup`.`jvm-ecosystem`: PluginDependencySpec get() = plugins.id("org.gradle.jvm-ecosystem") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.jvm-test-suite` plugin implemented by [org.gradle.api.plugins.JvmTestSuitePlugin]. */ internal val `OrgGradlePluginGroup`.`jvm-test-suite`: PluginDependencySpec get() = plugins.id("org.gradle.jvm-test-suite") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.language-base` plugin implemented by [org.gradle.language.base.plugins.LanguageBasePlugin]. */ internal val `OrgGradlePluginGroup`.`language-base`: PluginDependencySpec get() = plugins.id("org.gradle.language-base") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.lifecycle-base` plugin implemented by [org.gradle.language.base.plugins.LifecycleBasePlugin]. */ internal val `OrgGradlePluginGroup`.`lifecycle-base`: PluginDependencySpec get() = plugins.id("org.gradle.lifecycle-base") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.maven-publish` plugin implemented by [org.gradle.api.publish.maven.plugins.MavenPublishPlugin]. */ internal val `OrgGradlePluginGroup`.`maven-publish`: PluginDependencySpec get() = plugins.id("org.gradle.maven-publish") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.microsoft-visual-cpp-compiler` plugin implemented by [org.gradle.nativeplatform.toolchain.plugins.MicrosoftVisualCppCompilerPlugin]. */ internal val `OrgGradlePluginGroup`.`microsoft-visual-cpp-compiler`: PluginDependencySpec get() = plugins.id("org.gradle.microsoft-visual-cpp-compiler") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.native-component-model` plugin implemented by [org.gradle.nativeplatform.plugins.NativeComponentModelPlugin]. */ internal val `OrgGradlePluginGroup`.`native-component-model`: PluginDependencySpec get() = plugins.id("org.gradle.native-component-model") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.native-component` plugin implemented by [org.gradle.nativeplatform.plugins.NativeComponentPlugin]. */ internal val `OrgGradlePluginGroup`.`native-component`: PluginDependencySpec get() = plugins.id("org.gradle.native-component") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.objective-c-lang` plugin implemented by [org.gradle.language.objectivec.plugins.ObjectiveCLangPlugin]. */ internal val `OrgGradlePluginGroup`.`objective-c-lang`: PluginDependencySpec get() = plugins.id("org.gradle.objective-c-lang") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.objective-c` plugin implemented by [org.gradle.language.objectivec.plugins.ObjectiveCPlugin]. */ internal val `OrgGradlePluginGroup`.`objective-c`: PluginDependencySpec get() = plugins.id("org.gradle.objective-c") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.objective-cpp-lang` plugin implemented by [org.gradle.language.objectivecpp.plugins.ObjectiveCppLangPlugin]. */ internal val `OrgGradlePluginGroup`.`objective-cpp-lang`: PluginDependencySpec get() = plugins.id("org.gradle.objective-cpp-lang") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.objective-cpp` plugin implemented by [org.gradle.language.objectivecpp.plugins.ObjectiveCppPlugin]. */ internal val `OrgGradlePluginGroup`.`objective-cpp`: PluginDependencySpec get() = plugins.id("org.gradle.objective-cpp") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.pmd` plugin implemented by [org.gradle.api.plugins.quality.PmdPlugin]. */ internal val `OrgGradlePluginGroup`.`pmd`: PluginDependencySpec get() = plugins.id("org.gradle.pmd") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.project-report` plugin implemented by [org.gradle.api.plugins.ProjectReportsPlugin]. */ internal val `OrgGradlePluginGroup`.`project-report`: PluginDependencySpec get() = plugins.id("org.gradle.project-report") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.project-reports` plugin implemented by [org.gradle.api.plugins.ProjectReportsPlugin]. */ internal val `OrgGradlePluginGroup`.`project-reports`: PluginDependencySpec get() = plugins.id("org.gradle.project-reports") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.publishing` plugin implemented by [org.gradle.api.publish.plugins.PublishingPlugin]. */ internal val `OrgGradlePluginGroup`.`publishing`: PluginDependencySpec get() = plugins.id("org.gradle.publishing") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.reporting-base` plugin implemented by [org.gradle.api.plugins.ReportingBasePlugin]. */ internal val `OrgGradlePluginGroup`.`reporting-base`: PluginDependencySpec get() = plugins.id("org.gradle.reporting-base") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.scala-base` plugin implemented by [org.gradle.api.plugins.scala.ScalaBasePlugin]. */ internal val `OrgGradlePluginGroup`.`scala-base`: PluginDependencySpec get() = plugins.id("org.gradle.scala-base") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.scala` plugin implemented by [org.gradle.api.plugins.scala.ScalaPlugin]. */ internal val `OrgGradlePluginGroup`.`scala`: PluginDependencySpec get() = plugins.id("org.gradle.scala") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.signing` plugin implemented by [org.gradle.plugins.signing.SigningPlugin]. */ internal val `OrgGradlePluginGroup`.`signing`: PluginDependencySpec get() = plugins.id("org.gradle.signing") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.standard-tool-chains` plugin implemented by [org.gradle.nativeplatform.toolchain.internal.plugins.StandardToolChainsPlugin]. */ internal val `OrgGradlePluginGroup`.`standard-tool-chains`: PluginDependencySpec get() = plugins.id("org.gradle.standard-tool-chains") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.swift-application` plugin implemented by [org.gradle.language.swift.plugins.SwiftApplicationPlugin]. */ internal val `OrgGradlePluginGroup`.`swift-application`: PluginDependencySpec get() = plugins.id("org.gradle.swift-application") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.swift-library` plugin implemented by [org.gradle.language.swift.plugins.SwiftLibraryPlugin]. */ internal val `OrgGradlePluginGroup`.`swift-library`: PluginDependencySpec get() = plugins.id("org.gradle.swift-library") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.swiftpm-export` plugin implemented by [org.gradle.swiftpm.plugins.SwiftPackageManagerExportPlugin]. */ internal val `OrgGradlePluginGroup`.`swiftpm-export`: PluginDependencySpec get() = plugins.id("org.gradle.swiftpm-export") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.test-report-aggregation` plugin implemented by [org.gradle.api.plugins.TestReportAggregationPlugin]. */ internal val `OrgGradlePluginGroup`.`test-report-aggregation`: PluginDependencySpec get() = plugins.id("org.gradle.test-report-aggregation") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.test-suite-base` plugin implemented by [org.gradle.testing.base.plugins.TestSuiteBasePlugin]. */ internal val `OrgGradlePluginGroup`.`test-suite-base`: PluginDependencySpec get() = plugins.id("org.gradle.test-suite-base") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.validate-external-gradle-plugin` plugin implemented by [org.gradle.plugin.devel.plugins.ExternalPluginValidationPlugin]. */ internal val `OrgGradlePluginGroup`.`validate-external-gradle-plugin`: PluginDependencySpec get() = plugins.id("org.gradle.validate-external-gradle-plugin") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.version-catalog` plugin implemented by [org.gradle.api.plugins.catalog.VersionCatalogPlugin]. */ internal val `OrgGradlePluginGroup`.`version-catalog`: PluginDependencySpec get() = plugins.id("org.gradle.version-catalog") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.visual-studio` plugin implemented by [org.gradle.ide.visualstudio.plugins.VisualStudioPlugin]. */ internal val `OrgGradlePluginGroup`.`visual-studio`: PluginDependencySpec get() = plugins.id("org.gradle.visual-studio") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.war` plugin implemented by [org.gradle.api.plugins.WarPlugin]. */ internal val `OrgGradlePluginGroup`.`war`: PluginDependencySpec get() = plugins.id("org.gradle.war") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.windows-resource-script` plugin implemented by [org.gradle.language.rc.plugins.WindowsResourceScriptPlugin]. */ internal val `OrgGradlePluginGroup`.`windows-resource-script`: PluginDependencySpec get() = plugins.id("org.gradle.windows-resource-script") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.windows-resources` plugin implemented by [org.gradle.language.rc.plugins.WindowsResourcesPlugin]. */ internal val `OrgGradlePluginGroup`.`windows-resources`: PluginDependencySpec get() = plugins.id("org.gradle.windows-resources") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.wrapper` plugin implemented by [org.gradle.buildinit.plugins.WrapperPlugin]. */ internal val `OrgGradlePluginGroup`.`wrapper`: PluginDependencySpec get() = plugins.id("org.gradle.wrapper") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.xcode` plugin implemented by [org.gradle.ide.xcode.plugins.XcodePlugin]. */ internal val `OrgGradlePluginGroup`.`xcode`: PluginDependencySpec get() = plugins.id("org.gradle.xcode") - TopLevelPropertyNaming:PluginSpecBuilders.kt$/** * The `org.gradle.xctest` plugin implemented by [org.gradle.nativeplatform.test.xctest.plugins.XCTestConventionPlugin]. */ internal val `OrgGradlePluginGroup`.`xctest`: PluginDependencySpec get() = plugins.id("org.gradle.xctest") - UnnecessaryAbstractClass:SimpleScriptTest.kt$SimpleScript$SimpleScript - UnnecessaryAbstractClass:SomeSuperClass.kt$SomeSuperClass$SomeSuperClass - UnnecessaryAbstractClass:samefile.kt$CanPrint$CanPrint - UnusedPrivateClass:CompiledFileExample.kt$CompiledFileExample - UnusedPrivateClass:Constructor.kt$SomeConstructor - UnusedPrivateClass:DocumentSymbols.kt$DocumentSymbols - UnusedPrivateClass:FileToEdit.kt$FileToEdit - UnusedPrivateClass:FunctionScope.kt$FunctionScope - UnusedPrivateClass:LintErrors.kt$LintErrors - UnusedPrivateClass:MainWorkspaceFile.kt$MainWorkspaceFile - UnusedPrivateClass:MiddleOfFunction.kt$MiddleOfFunction - UnusedPrivateClass:ReferenceGetSetValue.kt$Main - UnusedPrivateClass:Types.kt$Types - UnusedPrivateClass:Visibility.kt$Visibility : VisibilitySuper - UnusedPrivateMember:BackquotedFunction.kt$private fun `fun that needs backquotes`() - UnusedPrivateMember:BackquotedFunction.kt$private fun completeBackquotedFunction() - UnusedPrivateMember:BigFile.kt$BigFile$args: Array<String> UnusedPrivateMember:Completions.kt$private fun completeTypeMembers(type: KotlinType): Sequence<DeclarationDescriptor> - UnusedPrivateMember:Completions.kt$private fun empty(message: String): CompletionList - UnusedPrivateMember:Constructor.kt$SomeConstructor$x: Int - UnusedPrivateMember:Constructor.kt$private fun main() - UnusedPrivateMember:DebouncerTest.kt$DebouncerTest$i - UnusedPrivateMember:DocumentSymbols.kt$DocumentSymbols$aConstructorArg: Int - UnusedPrivateMember:DocumentSymbols.kt$DocumentSymbols$aFunctionArg: Int - UnusedPrivateMember:DoubleDot.kt$private fun doubleDot(p: String) - UnusedPrivateMember:EditCall.kt$private fun test() - UnusedPrivateMember:FunctionReference.kt$private fun foo(): List<String> - UnusedPrivateMember:FunctionScope.kt$FunctionScope$anArgument: Int - UnusedPrivateMember:FunctionScope.kt$FunctionScope$private fun aClassFun() - UnusedPrivateMember:FunctionScope.kt$FunctionScope$private val aClassVal = 1 - UnusedPrivateMember:FunctionScope.kt$FunctionScope$val aLocal = 1 - UnusedPrivateMember:FunctionScope.kt$FunctionScope.Companion$private fun aCompanionFun() - UnusedPrivateMember:FunctionScope.kt$FunctionScope.Companion$private val aCompanionVal = 1 - UnusedPrivateMember:FunctionScript.kts$val first = 1 - UnusedPrivateMember:FunctionScript.kts$val second = 2 - UnusedPrivateMember:GradleClassPathResolver.kt$private val gradleErrorWherePattern by lazy { "\\*\\s+Where:[\r\n]+(\\S\\.*)".toRegex() } - UnusedPrivateMember:InstanceMember.kt$SomeClass$private fun privateInstanceFoo() - UnusedPrivateMember:InstanceMember.kt$private fun SomeClass.extensionFoo() - UnusedPrivateMember:InstanceMember.kt$private fun completeIdentifierInsideCall() - UnusedPrivateMember:InstanceMember.kt$private fun findCompletionsForLettersInFullMethod() - UnusedPrivateMember:InstanceMember.kt$private fun findFunctionReference() - UnusedPrivateMember:InstanceMember.kt$private fun findListExtensionFunctions() - UnusedPrivateMember:InstanceMember.kt$private fun findUnqualifiedFunctionReference() - UnusedPrivateMember:InstanceMember.kt$private fun foo() - UnusedPrivateMember:InstanceMembersJava.kt$private fun findJavaInstanceMembers(p: Path) UnusedPrivateMember:JavaElementConverter.kt$JavaElementConverter$private fun PsiCallExpression.translateTypeArguments(): String - UnusedPrivateMember:KotlinTextDocumentService.kt$KotlinTextDocumentService$private val TextDocumentIdentifier.isKotlinScript: Boolean get() = uri.endsWith(".kts") - UnusedPrivateMember:LintTest.kt$LintTest$i - UnusedPrivateMember:Literals.kt$private fun foo() UnusedPrivateMember:Logger.kt$Logger$private val newline = System.lineSeparator() - UnusedPrivateMember:ObjectReference.kt$private fun bar() - UnusedPrivateMember:ObjectReference.kt$private fun dang() - UnusedPrivateMember:ObjectReference.kt$private fun foo() - UnusedPrivateMember:OtherFileSymbols.kt$OtherFileSymbols$aConstructorArg: Int - UnusedPrivateMember:OtherFileSymbols.kt$OtherFileSymbols$val otherFileLocalVariable = 1 - UnusedPrivateMember:OuterDotInner.kt$private fun staticDot() - UnusedPrivateMember:OuterDotInner.kt$private fun test(p: Any) - UnusedPrivateMember:QuestionDot.kt$private fun completeQuestionDot(s: String?) - UnusedPrivateMember:Recover.kt$private fun blockFunction() - UnusedPrivateMember:Recover.kt$private fun intFunction() - UnusedPrivateMember:Recover.kt$private fun singleExpressionFunction() - UnusedPrivateMember:ReferenceCollectionish.kt$i - UnusedPrivateMember:ReferenceCollectionish.kt$private fun main() - UnusedPrivateMember:ReferenceComponents.kt$private fun main() - UnusedPrivateMember:ReferenceComponents.kt$val c = ReferenceComponents().component1() - UnusedPrivateMember:ReferenceConstructor.kt$ReferenceConstructor$mainConstructor: String - UnusedPrivateMember:ReferenceConstructor.kt$private fun main() - UnusedPrivateMember:ReferenceGetSetValue.kt$Main$private fun main() - UnusedPrivateMember:ReferenceGetterSetter.kt$private fun main() - UnusedPrivateMember:ReferenceInvoke.kt$private fun main() - UnusedPrivateMember:ReferenceOperator.kt$private fun main() - UnusedPrivateMember:ReferenceOperatorUsingName.kt$private fun main() - UnusedPrivateMember:SignatureHelp.kt$SignatureHelp$param: String - UnusedPrivateMember:SignatureHelp.kt$Target$bar: Int - UnusedPrivateMember:SignatureHelp.kt$Target$bar: String - UnusedPrivateMember:SignatureHelp.kt$Target$first: Int - UnusedPrivateMember:SignatureHelp.kt$Target$first: String - UnusedPrivateMember:SignatureHelp.kt$Target$second: Int - UnusedPrivateMember:SignatureHelp.kt$Target$second: String - UnusedPrivateMember:SimpleScriptTest.kt$SimpleScriptTest$val resultValue = (result as ResultWithDiagnostics.Success).value.returnValue as ResultValue.Value UnusedPrivateMember:SourceFiles.kt$i - UnusedPrivateMember:Statics.kt$private fun completeStatics() - UnusedPrivateMember:TrailingLambda.kt$a: Int - UnusedPrivateMember:TrailingLambda.kt$b: (Int) -> Unit - UnusedPrivateMember:TrailingLambda.kt$x: () -> Unit - UnusedPrivateMember:Visibility.kt$Visibility$private fun privateThisFun() - UnusedPrivateMember:Visibility.kt$Visibility.Companion$private fun privateThisCompanionFun() - UnusedPrivateMember:Visibility.kt$VisibilitySuper$private fun privateSuperFun() - UnusedPrivateMember:Visibility.kt$VisibilitySuper.Companion$private fun privateSuperCompanionFun() - UnusedPrivateMember:Visibility.kt$private fun privateTopLevelFun() - UtilityClassWithPublicConstructor:CompanionObject.kt$SweetPotato - UtilityClassWithPublicConstructor:Statics.kt$MyClass - WildcardImport:Accessors46nwrg1rs44ofdqpi7vyy3pfc.kt$import org.gradle.kotlin.dsl.* - WildcardImport:Accessors46nwrg1rs44ofdqpi7vyy3pfc.kt$import org.gradle.kotlin.dsl.accessors.runtime.* - WildcardImport:Accessors6xcmy081jxud3rx4r453mbm9f.kt$import org.gradle.kotlin.dsl.* - WildcardImport:Accessors6xcmy081jxud3rx4r453mbm9f.kt$import org.gradle.kotlin.dsl.accessors.runtime.* - WildcardImport:Accessors8lcri9ibgd9oj8dt3t8z8nvfx.kt$import org.gradle.kotlin.dsl.* - WildcardImport:Accessors8lcri9ibgd9oj8dt3t8z8nvfx.kt$import org.gradle.kotlin.dsl.accessors.runtime.* - WildcardImport:Accessorsasa455whv8s4bk3c97fzgde0p.kt$import org.gradle.kotlin.dsl.* - WildcardImport:Accessorsasa455whv8s4bk3c97fzgde0p.kt$import org.gradle.kotlin.dsl.accessors.runtime.* - WildcardImport:Accessorsb13nju9doius8kxwhlptqirtr.kt$import org.gradle.kotlin.dsl.* - WildcardImport:Accessorsb13nju9doius8kxwhlptqirtr.kt$import org.gradle.kotlin.dsl.accessors.runtime.* - WildcardImport:Accessorsblypoh2ruc9u3bx9djsfqsntg.kt$import org.gradle.kotlin.dsl.* - WildcardImport:Accessorsblypoh2ruc9u3bx9djsfqsntg.kt$import org.gradle.kotlin.dsl.accessors.runtime.* - WildcardImport:Accessorscchdiujech8u294vwhihsq7gh.kt$import org.gradle.kotlin.dsl.* - WildcardImport:Accessorscchdiujech8u294vwhihsq7gh.kt$import org.gradle.kotlin.dsl.accessors.runtime.* WildcardImport:AddMissingImportsQuickFix.kt$import org.eclipse.lsp4j.* - WildcardImport:AdditionalWorkspaceTest.kt$import org.hamcrest.Matchers.* - WildcardImport:ClassPathTest.kt$import org.hamcrest.Matchers.* - WildcardImport:ClassPathTest.kt$import org.javacs.kt.classpath.* WildcardImport:CodeAction.kt$import org.eclipse.lsp4j.* WildcardImport:CompiledFile.kt$import org.jetbrains.kotlin.psi.* - WildcardImport:Compiler.kt$import org.jetbrains.kotlin.config.* WildcardImport:Compiler.kt$import org.jetbrains.kotlin.psi.* WildcardImport:Completions.kt$import org.jetbrains.kotlin.descriptors.* WildcardImport:Completions.kt$import org.jetbrains.kotlin.psi.* WildcardImport:Completions.kt$import org.jetbrains.kotlin.psi.psiUtil.* WildcardImport:Completions.kt$import org.jetbrains.kotlin.resolve.descriptorUtil.* - WildcardImport:CompletionsTest.kt$import org.hamcrest.Matchers.* WildcardImport:ExtractSymbolExtensionReceiverType.kt$import org.jetbrains.kotlin.descriptors.* WildcardImport:ExtractSymbolKind.kt$import org.jetbrains.kotlin.descriptors.* WildcardImport:ExtractSymbolVisibility.kt$import org.jetbrains.kotlin.descriptors.* WildcardImport:FindReferences.kt$import org.jetbrains.kotlin.psi.* - WildcardImport:GradleDSLScriptTest.kt$import org.hamcrest.Matchers.* - WildcardImport:HoverTest.kt$import org.hamcrest.Matchers.* WildcardImport:Hovers.kt$import org.jetbrains.kotlin.psi.* WildcardImport:ImplementAbstractMembersQuickFix.kt$import org.eclipse.lsp4j.* WildcardImport:Imports.kt$import org.jetbrains.kotlin.psi.* - WildcardImport:ImportsTest.kt$import org.hamcrest.Matchers.* WildcardImport:JavaElementConverter.kt$import com.intellij.psi.* WildcardImport:JavaElementConverter.kt$import com.intellij.psi.javadoc.* WildcardImport:JavaTypeConverter.kt$import com.intellij.psi.* - WildcardImport:KotlinLanguageServer.kt$import org.eclipse.lsp4j.* - WildcardImport:KotlinLanguageServer.kt$import org.javacs.kt.externalsources.* WildcardImport:KotlinProtocolExtensionService.kt$import org.eclipse.lsp4j.* WildcardImport:KotlinProtocolExtensions.kt$import org.eclipse.lsp4j.* WildcardImport:KotlinTextDocumentService.kt$import org.eclipse.lsp4j.* - WildcardImport:KotlinTextDocumentService.kt$import org.javacs.kt.completion.* WildcardImport:KotlinWorkspaceService.kt$import org.eclipse.lsp4j.* - WildcardImport:LanguageServerTestFixture.kt$import org.eclipse.lsp4j.* - WildcardImport:LintTest.kt$import org.hamcrest.Matchers.* - WildcardImport:MavenArtifactParsingTest.kt$import org.hamcrest.Matchers.* - WildcardImport:OneFilePerformance.kt$import org.openjdk.jmh.annotations.* - WildcardImport:ReferencesTest.kt$import org.hamcrest.Matchers.* WildcardImport:Rename.kt$import org.eclipse.lsp4j.* WildcardImport:RenderCompletionItem.kt$import org.jetbrains.kotlin.descriptors.* - WildcardImport:SemanticTokensTest.kt$import org.hamcrest.Matchers.* - WildcardImport:SignatureHelpTest.kt$import org.hamcrest.Matchers.* - WildcardImport:SimpleScriptTest.kt$import kotlin.script.experimental.api.* - WildcardImport:SimpleScriptTest.kt$import org.hamcrest.Matchers.* - WildcardImport:SimpleScriptTest.kt$import org.junit.* - WildcardImport:SimpleScriptTest.kt$import org.junit.Assert.* WildcardImport:SymbolIndex.kt$import org.jetbrains.exposed.sql.* WildcardImport:Symbols.kt$import org.jetbrains.kotlin.psi.* diff --git a/server/src/main/kotlin/org/javacs/kt/CompiledFile.kt b/server/src/main/kotlin/org/javacs/kt/CompiledFile.kt index ca884b63d..22faacf22 100644 --- a/server/src/main/kotlin/org/javacs/kt/CompiledFile.kt +++ b/server/src/main/kotlin/org/javacs/kt/CompiledFile.kt @@ -2,7 +2,7 @@ package org.javacs.kt import com.intellij.openapi.util.TextRange import com.intellij.psi.PsiElement -import org.javacs.kt.compiler.CompilationKind +import org.javacs.kt.compiler.CompilationType import org.javacs.kt.position.changedRegion import org.javacs.kt.position.location import org.javacs.kt.position.position @@ -29,10 +29,10 @@ class CompiledFile( val parse: KtFile, val compile: BindingContext, val module: ModuleDescriptor, - val sourcePath: Collection, - val classPath: CompilerClassPath, - val isScript: Boolean = false, - val kind: CompilationKind = CompilationKind.DEFAULT + private val sourcePath: Collection, + private val classPath: CompilerClassPath, + private val isScript: Boolean = false, + val kind: CompilationType = CompilationType.DEFAULT ) { /** * Find the type of the expression at `cursor` @@ -99,9 +99,9 @@ class CompiledFile( private fun expandForReference(cursor: Int, surroundingExpr: KtExpression): KtExpression { val parent: KtExpression? = - surroundingExpr.parent as? KtDotQualifiedExpression // foo.bar - ?: surroundingExpr.parent as? KtSafeQualifiedExpression // foo?.bar - ?: surroundingExpr.parent as? KtCallExpression // foo() + surroundingExpr.parent as? KtDotQualifiedExpression + ?: surroundingExpr.parent as? KtSafeQualifiedExpression + ?: surroundingExpr.parent as? KtCallExpression return parent?.let { expandForReference(cursor, it) } ?: surroundingExpr } @@ -155,12 +155,12 @@ class CompiledFile( // Otherwise just use the expression val recoveryRange = parent.textRange - LOG.info("Re-parsing {}", describeRange(recoveryRange, true)) + LOG.info("Re-parsing {}", describeRange(recoveryRange)) surroundingContent = content.substring(recoveryRange.startOffset, content.length - (parse.text.length - recoveryRange.endOffset)) offset = recoveryRange.startOffset - if (asReference && !((parent as? KtParameter)?.hasValOrVar() ?: true)) { + if (asReference && (parent as? KtParameter)?.hasValOrVar() == false) { // Prepend 'val' to (e.g. function) parameters val prefix = "val " surroundingContent = prefix + surroundingContent @@ -264,7 +264,7 @@ class CompiledFile( return "$file ${pos.line + 1}:${pos.character + 1}" } - private fun describeRange(range: TextRange, oldContent: Boolean = false): String { + private fun describeRange(range: TextRange, oldContent: Boolean = true): String { val c = if (oldContent) parse.text else content val start = position(c, range.startOffset) val end = position(c, range.endOffset) diff --git a/server/src/main/kotlin/org/javacs/kt/CompilerClassPath.kt b/server/src/main/kotlin/org/javacs/kt/CompilerClassPath.kt index 794377454..c8fc8a698 100644 --- a/server/src/main/kotlin/org/javacs/kt/CompilerClassPath.kt +++ b/server/src/main/kotlin/org/javacs/kt/CompilerClassPath.kt @@ -5,6 +5,7 @@ import org.javacs.kt.classpath.defaultClassPathResolver import org.javacs.kt.compiler.Compiler import org.javacs.kt.database.DatabaseService import org.javacs.kt.util.AsyncExecutor +import org.javacs.kt.util.KotlinLSException import java.io.Closeable import java.io.File import java.nio.file.FileSystems @@ -39,7 +40,7 @@ class CompilerClassPath( ) private set - private val async = AsyncExecutor() + private val asyncExecutor = AsyncExecutor(name = "CompilerClassPath") init { compiler.updateConfiguration(config) @@ -64,7 +65,7 @@ class CompilerClassPath( refreshCompiler = true } - async.compute { + asyncExecutor.compute { val newClassPathWithSources = resolver.classpathWithSources synchronized(classPath) { syncPaths(classPath, newClassPathWithSources, "class path with sources") { it.compiledJar } @@ -170,7 +171,12 @@ class CompilerClassPath( override fun close() { compiler.close() - outputDirectory.delete() + outputDirectory.delete().also { deleted -> + if (!deleted) { + throw KotlinLSException("Failed to delete output directory: $outputDirectory") + } + LOG.info("Deleted output directory: $outputDirectory") + } } } diff --git a/server/src/main/kotlin/org/javacs/kt/Configuration.kt b/server/src/main/kotlin/org/javacs/kt/Configuration.kt index 58d615ab2..b557807a6 100644 --- a/server/src/main/kotlin/org/javacs/kt/Configuration.kt +++ b/server/src/main/kotlin/org/javacs/kt/Configuration.kt @@ -12,21 +12,21 @@ import java.nio.file.InvalidPathException import java.nio.file.Path import java.nio.file.Paths -public data class SnippetsConfiguration( +data class SnippetsConfiguration( /** Whether code completion should return VSCode-style snippets. */ var enabled: Boolean = true ) -public data class CodegenConfiguration( +data class CodegenConfiguration( /** Whether to enable code generation to a temporary build directory for Java interoperability. */ var enabled: Boolean = false ) -public data class CompletionConfiguration( +data class CompletionConfiguration( val snippets: SnippetsConfiguration = SnippetsConfiguration() ) -public data class DiagnosticsConfiguration( +data class DiagnosticsConfiguration( /** Whether diagnostics are enabled. */ var enabled: Boolean = true, /** The minimum severity of enabled diagnostics. */ @@ -35,21 +35,21 @@ public data class DiagnosticsConfiguration( var debounceTime: Long = 250L ) -public data class JVMConfiguration( +data class JVMConfiguration( /** Which JVM target the Kotlin compiler uses. See Compiler.jvmTargetFrom for possible values. */ var target: String = "default" ) -public data class CompilerConfiguration( +data class CompilerConfiguration( val jvm: JVMConfiguration = JVMConfiguration() ) -public data class IndexingConfiguration( +data class IndexingConfiguration( /** Whether an index of global symbols should be built in the background. */ var enabled: Boolean = true ) -public data class ExternalSourcesConfiguration( +data class ExternalSourcesConfiguration( /** Whether kls-URIs should be sent to the client to describe classes in JARs. */ var useKlsScheme: Boolean = false, /** Whether external classes should be automatically converted to Kotlin. */ @@ -104,7 +104,7 @@ class GsonPathConverter : JsonDeserializer { } } -public data class Configuration( +data class Configuration( val codegen: CodegenConfiguration = CodegenConfiguration(), val compiler: CompilerConfiguration = CompilerConfiguration(), val completion: CompletionConfiguration = CompletionConfiguration(), diff --git a/server/src/main/kotlin/org/javacs/kt/KotlinProtocolExtensionService.kt b/server/src/main/kotlin/org/javacs/kt/KotlinProtocolExtensionService.kt index 76428a510..3835e6fa4 100644 --- a/server/src/main/kotlin/org/javacs/kt/KotlinProtocolExtensionService.kt +++ b/server/src/main/kotlin/org/javacs/kt/KotlinProtocolExtensionService.kt @@ -14,27 +14,27 @@ class KotlinProtocolExtensionService( private val cp: CompilerClassPath, private val sp: SourcePath ) : KotlinProtocolExtensions { - private val async = AsyncExecutor() + private val asyncExecutor = AsyncExecutor(name = "KotlinProtocolExtensionService") - override fun jarClassContents(textDocument: TextDocumentIdentifier): CompletableFuture = async.compute { + override fun jarClassContents(textDocument: TextDocumentIdentifier): CompletableFuture = asyncExecutor.compute { uriContentProvider.contentOf(parseURI(textDocument.uri)) } - override fun buildOutputLocation(): CompletableFuture = async.compute { + override fun buildOutputLocation(): CompletableFuture = asyncExecutor.compute { cp.outputDirectory.absolutePath } - override fun mainClass(textDocument: TextDocumentIdentifier): CompletableFuture> = async.compute { + override fun mainClass(textDocument: TextDocumentIdentifier): CompletableFuture> = asyncExecutor.compute { val fileUri = parseURI(textDocument.uri) val filePath = Paths.get(fileUri) - + // we find the longest one in case both the root and submodule are included val workspacePath = cp.workspaceRoots.filter { filePath.startsWith(it) }.map { it.toString() }.maxByOrNull(String::length) ?: "" - + val compiledFile = sp.currentVersion(fileUri) resolveMain(compiledFile) + mapOf( @@ -42,7 +42,7 @@ class KotlinProtocolExtensionService( ) } - override fun overrideMember(position: TextDocumentPositionParams): CompletableFuture> = async.compute { + override fun overrideMember(position: TextDocumentPositionParams): CompletableFuture> = asyncExecutor.compute { val fileUri = parseURI(position.textDocument.uri) val compiledFile = sp.currentVersion(fileUri) val cursorOffset = offset(compiledFile.content, position.position) diff --git a/server/src/main/kotlin/org/javacs/kt/KotlinTextDocumentService.kt b/server/src/main/kotlin/org/javacs/kt/KotlinTextDocumentService.kt index 2ec1e5227..e51b5b073 100644 --- a/server/src/main/kotlin/org/javacs/kt/KotlinTextDocumentService.kt +++ b/server/src/main/kotlin/org/javacs/kt/KotlinTextDocumentService.kt @@ -1,24 +1,29 @@ package org.javacs.kt +import java.io.Closeable +import java.net.URI +import java.nio.file.Path +import java.time.Duration +import java.util.concurrent.CompletableFuture import org.eclipse.lsp4j.* import org.eclipse.lsp4j.jsonrpc.messages.Either import org.eclipse.lsp4j.services.LanguageClient import org.eclipse.lsp4j.services.TextDocumentService import org.javacs.kt.codeaction.codeActions import org.javacs.kt.completion.completions -import org.javacs.kt.definition.goToDefinition +import org.javacs.kt.definition.DefinitionHandler import org.javacs.kt.diagnostic.convertDiagnostic import org.javacs.kt.formatting.FormattingService +import org.javacs.kt.highlight.documentHighlightsAt import org.javacs.kt.hover.hoverAt -import org.javacs.kt.position.offset +import org.javacs.kt.inlayhints.provideHints import org.javacs.kt.position.extractRange +import org.javacs.kt.position.offset import org.javacs.kt.position.position import org.javacs.kt.references.findReferences +import org.javacs.kt.rename.renameSymbol import org.javacs.kt.semantictokens.encodedSemanticTokens import org.javacs.kt.signaturehelp.fetchSignatureHelpAt -import org.javacs.kt.rename.renameSymbol -import org.javacs.kt.highlight.documentHighlightsAt -import org.javacs.kt.inlayhints.provideHints import org.javacs.kt.symbols.documentSymbols import org.javacs.kt.util.AsyncExecutor import org.javacs.kt.util.Debouncer @@ -29,161 +34,206 @@ import org.javacs.kt.util.filePath import org.javacs.kt.util.noResult import org.javacs.kt.util.parseURI import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics -import java.net.URI -import java.io.Closeable -import java.nio.file.Path -import java.time.Duration -import java.util.concurrent.CompletableFuture class KotlinTextDocumentService( - private val sf: SourceFiles, - private val sp: SourcePath, + private val sourceFiles: SourceFiles, + private val sourcePath: SourcePath, private val config: Configuration, - private val tempDirectory: TemporaryDirectory, - private val uriContentProvider: URIContentProvider, - private val cp: CompilerClassPath + tempDirectory: TemporaryDirectory, + uriContentProvider: URIContentProvider, + cp: CompilerClassPath, ) : TextDocumentService, Closeable { private lateinit var client: LanguageClient - private val async = AsyncExecutor() + private val asyncExecutor = AsyncExecutor(name = "KotlinTextDocumentService") private val formattingService = FormattingService(config.formatting) - - var debounceLint = Debouncer(Duration.ofMillis(config.diagnostics.debounceTime)) + private val definitionHandler = + DefinitionHandler( + uriContentProvider.classContentProvider, + tempDirectory, + config.externalSources, + cp, + ) + + var lintDebouncer = Debouncer(Duration.ofMillis(config.diagnostics.debounceTime)) val lintTodo = mutableSetOf() var lintCount = 0 var lintRecompilationCallback: () -> Unit - get() = sp.beforeCompileCallback - set(callback) { sp.beforeCompileCallback = callback } - - private val TextDocumentItem.filePath: Path? - get() = parseURI(uri).filePath + get() = sourcePath.beforeCompileCallback + set(callback) { + sourcePath.beforeCompileCallback = callback + } private val TextDocumentIdentifier.filePath: Path? get() = parseURI(uri).filePath - private val TextDocumentIdentifier.isKotlinScript: Boolean - get() = uri.endsWith(".kts") - private val TextDocumentIdentifier.content: String - get() = sp.content(parseURI(uri)) + get() = sourcePath.content(parseURI(uri)) fun connect(client: LanguageClient) { this.client = client } private enum class Recompile { - ALWAYS, AFTER_DOT, NEVER + ALWAYS, + AFTER_DOT, + NEVER, } - private fun recover(position: TextDocumentPositionParams, recompile: Recompile): Pair? { + private fun recover( + position: TextDocumentPositionParams, + recompile: Recompile = Recompile.NEVER, + ): Pair? { return recover(position.textDocument.uri, position.position, recompile) } - private fun recover(uriString: String, position: Position, recompile: Recompile): Pair? { + private fun recover( + uriString: String, + position: Position, + recompile: Recompile, + ): Pair? { val uri = parseURI(uriString) - if (!sf.isIncluded(uri)) { + if (!sourceFiles.isIncluded(uri)) { LOG.warn("URI is excluded, therefore cannot be recovered: $uri") return null } - val content = sp.content(uri) + val content = sourcePath.content(uri) val offset = offset(content, position.line, position.character) - val shouldRecompile = when (recompile) { - Recompile.ALWAYS -> true - Recompile.AFTER_DOT -> offset > 0 && content[offset - 1] == '.' - Recompile.NEVER -> false - } - val compiled = if (shouldRecompile) sp.currentVersion(uri) else sp.latestCompiledVersion(uri) + val shouldRecompile = + when (recompile) { + Recompile.ALWAYS -> true + Recompile.AFTER_DOT -> offset > 0 && content[offset - 1] == '.' + Recompile.NEVER -> false + } + val compiled = + if (shouldRecompile) sourcePath.currentVersion(uri) + else sourcePath.latestCompiledVersion(uri) return Pair(compiled, offset) } - override fun codeAction(params: CodeActionParams): CompletableFuture>> = async.compute { - val (file, _) = recover(params.textDocument.uri, params.range.start, Recompile.NEVER) ?: return@compute emptyList() - codeActions(file, sp.index, params.range, params.context) - } + override fun codeAction( + params: CodeActionParams + ): CompletableFuture>> = + asyncExecutor.compute { + val (file, _) = + recover(params.textDocument.uri, params.range.start, Recompile.NEVER) + ?: return@compute emptyList() + codeActions(file, sourcePath.index, params.range, params.context) + } - override fun inlayHint(params: InlayHintParams): CompletableFuture> = async.compute { - val (file, _) = recover(params.textDocument.uri, params.range.start, Recompile.ALWAYS) ?: return@compute emptyList() - provideHints(file, config.inlayHints) - } + override fun inlayHint(params: InlayHintParams): CompletableFuture> = + asyncExecutor.compute { + val (file, _) = + recover(params.textDocument.uri, params.range.start, Recompile.ALWAYS) + ?: return@compute emptyList() + provideHints(file, config.inlayHints) + } - override fun hover(position: HoverParams): CompletableFuture = async.compute { - reportTime { - LOG.info("Hovering at {}", describePosition(position)) + override fun hover(position: HoverParams): CompletableFuture = + asyncExecutor.compute { + reportTime { + LOG.info("Hovering at {}", describePosition(position)) - val (file, cursor) = recover(position, Recompile.NEVER) ?: return@compute null - hoverAt(file, cursor) ?: noResult("No hover found at ${describePosition(position)}", null) + val (file, cursor) = recover(position) ?: return@compute null + hoverAt(file, cursor) + ?: noResult("No hover found at ${describePosition(position)}", null) + } } - } - override fun documentHighlight(position: DocumentHighlightParams): CompletableFuture> = async.compute { - val (file, cursor) = recover(position.textDocument.uri, position.position, Recompile.NEVER) ?: return@compute emptyList() - documentHighlightsAt(file, cursor) - } + override fun documentHighlight( + position: DocumentHighlightParams + ): CompletableFuture> = + asyncExecutor.compute { + val (file, cursor) = + recover(position.textDocument.uri, position.position, Recompile.NEVER) + ?: return@compute emptyList() + documentHighlightsAt(file, cursor) + } - override fun onTypeFormatting(params: DocumentOnTypeFormattingParams): CompletableFuture> { + override fun onTypeFormatting( + params: DocumentOnTypeFormattingParams + ): CompletableFuture> { TODO("not implemented") } - override fun definition(position: DefinitionParams): CompletableFuture, List>> = async.compute { - reportTime { - LOG.info("Go-to-definition at {}", describePosition(position)) - - val (file, cursor) = recover(position, Recompile.NEVER) ?: return@compute Either.forLeft(emptyList()) - goToDefinition(file, cursor, uriContentProvider.classContentProvider, tempDirectory, config.externalSources, cp) - ?.let(::listOf) - ?.let { Either.forLeft, List>(it) } - ?: noResult("Couldn't find definition at ${describePosition(position)}", Either.forLeft(emptyList())) + override fun definition( + position: DefinitionParams + ): CompletableFuture, List>> = + asyncExecutor.compute { + reportTime { + LOG.info("Go-to-definition at {}", describePosition(position)) + + val (file, cursor) = recover(position) ?: return@compute Either.forLeft(emptyList()) + definitionHandler.goToDefinition(file, cursor)?.let(::listOf)?.let { + Either.forLeft(it) + } + ?: noResult( + "Couldn't find definition at ${describePosition(position)}", + Either.forLeft(emptyList()), + ) + } } - } - override fun rangeFormatting(params: DocumentRangeFormattingParams): CompletableFuture> = async.compute { - val code = extractRange(params.textDocument.content, params.range) - listOf(TextEdit( - params.range, - formattingService.formatKotlinCode(code, params.options) - )) - } + override fun rangeFormatting( + params: DocumentRangeFormattingParams + ): CompletableFuture> = + asyncExecutor.compute { + val code = extractRange(params.textDocument.content, params.range) + listOf(TextEdit(params.range, formattingService.formatKotlinCode(code, params.options))) + } override fun codeLens(params: CodeLensParams): CompletableFuture> { TODO("not implemented") } - override fun rename(params: RenameParams) = async.compute { - val (file, cursor) = recover(params, Recompile.NEVER) ?: return@compute null - renameSymbol(file, cursor, sp, params.newName) - } - - override fun completion(position: CompletionParams): CompletableFuture, CompletionList>> = async.compute { - reportTime { - LOG.info("Completing at {}", describePosition(position)) - - val (file, cursor) = recover(position, Recompile.NEVER) ?: return@compute Either.forRight(CompletionList()) // TODO: Investigate when to recompile - val completions = completions(file, cursor, sp.index, config.completion) - LOG.info("Found {} items", completions.items.size) + override fun rename(params: RenameParams): CompletableFuture = + asyncExecutor.compute { + val (file, cursor) = recover(params, Recompile.NEVER) ?: return@compute null + renameSymbol(file, cursor, sourcePath, params.newName) + } - Either.forRight(completions) + override fun completion( + position: CompletionParams + ): CompletableFuture, CompletionList>> = + asyncExecutor.compute { + reportTime { + LOG.info("Completing at {}", describePosition(position)) + + val (file, cursor) = + recover(position) + ?: return@compute Either.forRight( + CompletionList() + ) // TODO: Investigate when to recompile + val completions = completions(file, cursor, sourcePath.index, config.completion) + LOG.info("Found {} items", completions.items.size) + + Either.forRight(completions) + } } - } - override fun resolveCompletionItem(unresolved: CompletionItem): CompletableFuture { + override fun resolveCompletionItem( + unresolved: CompletionItem + ): CompletableFuture { TODO("not implemented") } - @Suppress("DEPRECATION") - override fun documentSymbol(params: DocumentSymbolParams): CompletableFuture>> = async.compute { - LOG.info("Find symbols in {}", describeURI(params.textDocument.uri)) + override fun documentSymbol( + params: DocumentSymbolParams + ): CompletableFuture>> = + asyncExecutor.compute { + LOG.info("Find symbols in {}", describeURI(params.textDocument.uri)) - reportTime { - val uri = parseURI(params.textDocument.uri) - val parsed = sp.parsedFile(uri) + reportTime { + val uri = parseURI(params.textDocument.uri) + val parsed = sourcePath.parsedFile(uri) - documentSymbols(parsed) + documentSymbols(parsed) + } } - } override fun didOpen(params: DidOpenTextDocumentParams) { val uri = parseURI(params.textDocument.uri) - sf.open(uri, params.textDocument.text, params.textDocument.version) + sourceFiles.open(uri, params.textDocument.text, params.textDocument.version) lintNow(uri) } @@ -191,77 +241,82 @@ class KotlinTextDocumentService( // Lint after saving to prevent inconsistent diagnostics val uri = parseURI(params.textDocument.uri) lintNow(uri) - debounceLint.schedule { - sp.save(uri) - } + lintDebouncer.schedule { sourcePath.save(uri) } } - override fun signatureHelp(position: SignatureHelpParams): CompletableFuture = async.compute { - reportTime { - LOG.info("Signature help at {}", describePosition(position)) + override fun signatureHelp(position: SignatureHelpParams): CompletableFuture = + asyncExecutor.compute { + reportTime { + LOG.info("Signature help at {}", describePosition(position)) - val (file, cursor) = recover(position, Recompile.NEVER) ?: return@compute null - fetchSignatureHelpAt(file, cursor) ?: noResult("No function call around ${describePosition(position)}", null) + val (file, cursor) = recover(position) ?: return@compute null + fetchSignatureHelpAt(file, cursor) + ?: noResult("No function call around ${describePosition(position)}", null) + } } - } override fun didClose(params: DidCloseTextDocumentParams) { val uri = parseURI(params.textDocument.uri) - sf.close(uri) + sourceFiles.close(uri) clearDiagnostics(uri) } - override fun formatting(params: DocumentFormattingParams): CompletableFuture> = async.compute { - val code = params.textDocument.content - LOG.info("Formatting {}", describeURI(params.textDocument.uri)) - listOf(TextEdit( - Range(Position(0, 0), position(code, code.length)), - formattingService.formatKotlinCode(code, params.options) - )) - } + override fun formatting(params: DocumentFormattingParams): CompletableFuture> = + asyncExecutor.compute { + val code = params.textDocument.content + LOG.info("Formatting {}", describeURI(params.textDocument.uri)) + listOf( + TextEdit( + Range(Position(0, 0), position(code, code.length)), + formattingService.formatKotlinCode(code, params.options), + ) + ) + } override fun didChange(params: DidChangeTextDocumentParams) { val uri = parseURI(params.textDocument.uri) - sf.edit(uri, params.textDocument.version, params.contentChanges) + sourceFiles.edit(uri, params.textDocument.version, params.contentChanges) lintLater(uri) } - override fun references(position: ReferenceParams) = async.compute { - position.textDocument.filePath - ?.let { file -> - val content = sp.content(parseURI(position.textDocument.uri)) + override fun references(position: ReferenceParams) = + asyncExecutor.compute { + position.textDocument.filePath?.let { file -> + val content = sourcePath.content(parseURI(position.textDocument.uri)) val offset = offset(content, position.position.line, position.position.character) - findReferences(file, offset, sp) + findReferences(file, offset, sourcePath) } - } + } - override fun semanticTokensFull(params: SemanticTokensParams) = async.compute { - LOG.info("Full semantic tokens in {}", describeURI(params.textDocument.uri)) + override fun semanticTokensFull(params: SemanticTokensParams) = + asyncExecutor.compute { + LOG.info("Full semantic tokens in {}", describeURI(params.textDocument.uri)) - reportTime { - val uri = parseURI(params.textDocument.uri) - val file = sp.currentVersion(uri) + reportTime { + val uri = parseURI(params.textDocument.uri) + val file = sourcePath.currentVersion(uri) - val tokens = encodedSemanticTokens(file) - LOG.info("Found {} tokens", tokens.size) + val tokens = encodedSemanticTokens(file) + LOG.info("Found {} tokens", tokens.size) - SemanticTokens(tokens) + SemanticTokens(tokens) + } } - } - override fun semanticTokensRange(params: SemanticTokensRangeParams) = async.compute { - LOG.info("Ranged semantic tokens in {}", describeURI(params.textDocument.uri)) + override fun semanticTokensRange(params: SemanticTokensRangeParams) = + asyncExecutor.compute { + LOG.info("Ranged semantic tokens in {}", describeURI(params.textDocument.uri)) - reportTime { - val uri = parseURI(params.textDocument.uri) - val file = sp.currentVersion(uri) + reportTime { + val uri = parseURI(params.textDocument.uri) + val file = sourcePath.currentVersion(uri) - val tokens = encodedSemanticTokens(file, params.range) - LOG.info("Found {} tokens", tokens.size) + val tokens = encodedSemanticTokens(file, params.range) + LOG.info("Found {} tokens", tokens.size) - SemanticTokens(tokens) + SemanticTokens(tokens) + } } - } override fun resolveCodeLens(unresolved: CodeLens): CompletableFuture { TODO("not implemented") @@ -271,15 +326,15 @@ class KotlinTextDocumentService( return "${describeURI(position.textDocument.uri)} ${position.position.line + 1}:${position.position.character + 1}" } - public fun updateDebouncer() { - debounceLint = Debouncer(Duration.ofMillis(config.diagnostics.debounceTime)) + fun updateDebouncer() { + lintDebouncer = Debouncer(Duration.ofMillis(config.diagnostics.debounceTime)) } fun lintAll() { - debounceLint.submitImmediately { - sp.compileAllFiles() - sp.saveAllFiles() - sp.refreshDependencyIndexes() + lintDebouncer.submitImmediately { + sourcePath.compileAllFiles() + sourcePath.saveAllFiles() + sourcePath.refreshDependencyIndexes() } } @@ -291,18 +346,18 @@ class KotlinTextDocumentService( private fun lintLater(uri: URI) { lintTodo.add(uri) - debounceLint.schedule(::doLint) + lintDebouncer.schedule(::doLint) } private fun lintNow(file: URI) { lintTodo.add(file) - debounceLint.submitImmediately(::doLint) + lintDebouncer.submitImmediately(::doLint) } private fun doLint(cancelCallback: () -> Boolean) { LOG.info("Linting {}", describeURIs(lintTodo)) val files = clearLint() - val context = sp.compileFiles(files) + val context = sourcePath.compileFiles(files) if (!cancelCallback.invoke()) { reportDiagnostics(files, context.diagnostics) } @@ -310,18 +365,23 @@ class KotlinTextDocumentService( } private fun reportDiagnostics(compiled: Collection, kotlinDiagnostics: Diagnostics) { - val langServerDiagnostics = kotlinDiagnostics - .flatMap(::convertDiagnostic) - .filter { config.diagnostics.enabled && it.second.severity <= config.diagnostics.level } + val langServerDiagnostics = + kotlinDiagnostics.flatMap(::convertDiagnostic).filter { + config.diagnostics.enabled && it.second.severity <= config.diagnostics.level + } val byFile = langServerDiagnostics.groupBy({ it.first }, { it.second }) for ((uri, diagnostics) in byFile) { - if (sf.isOpen(uri)) { + if (sourceFiles.isOpen(uri)) { client.publishDiagnostics(PublishDiagnosticsParams(uri.toString(), diagnostics)) LOG.info("Reported {} diagnostics in {}", diagnostics.size, describeURI(uri)) - } - else LOG.info("Ignore {} diagnostics in {} because it's not open", diagnostics.size, describeURI(uri)) + } else + LOG.info( + "Ignore {} diagnostics in {} because it's not open", + diagnostics.size, + describeURI(uri), + ) } val noErrors = compiled - byFile.keys @@ -338,17 +398,17 @@ class KotlinTextDocumentService( client.publishDiagnostics(PublishDiagnosticsParams(uri.toString(), listOf())) } - private fun shutdownExecutors(awaitTermination: Boolean) { - async.shutdown(awaitTermination) - debounceLint.shutdown(awaitTermination) + private fun shutdownExecutors(awaitTermination: Boolean = true) { + asyncExecutor.shutdown(awaitTermination) + lintDebouncer.shutdown(awaitTermination) } override fun close() { - shutdownExecutors(awaitTermination = true) + shutdownExecutors() } } -private inline fun reportTime(block: () -> T): T { +private inline fun reportTime(block: () -> T): T { val started = System.currentTimeMillis() try { return block() diff --git a/server/src/main/kotlin/org/javacs/kt/KotlinWorkspaceService.kt b/server/src/main/kotlin/org/javacs/kt/KotlinWorkspaceService.kt index de5afdfa0..f4db2d7cd 100644 --- a/server/src/main/kotlin/org/javacs/kt/KotlinWorkspaceService.kt +++ b/server/src/main/kotlin/org/javacs/kt/KotlinWorkspaceService.kt @@ -27,7 +27,7 @@ class KotlinWorkspaceService( private val gson = Gson() private var languageClient: LanguageClient? = null - override fun connect(client: LanguageClient): Unit { + override fun connect(client: LanguageClient) { languageClient = client } diff --git a/server/src/main/kotlin/org/javacs/kt/Main.kt b/server/src/main/kotlin/org/javacs/kt/Main.kt index 7e19897c9..9a887cec5 100644 --- a/server/src/main/kotlin/org/javacs/kt/Main.kt +++ b/server/src/main/kotlin/org/javacs/kt/Main.kt @@ -39,7 +39,7 @@ fun main(argv: Array) { tcpStartServer(it) } ?: Pair(System.`in`, System.out) - val server = KotlinLanguageServer() + val server = Server() val threads = Executors.newSingleThreadExecutor { Thread(it, "client") } val launcher = LSPLauncher.createServerLauncher(server, ExitingInputStream(inStream), outStream, threads) { it } diff --git a/server/src/main/kotlin/org/javacs/kt/KotlinLanguageServer.kt b/server/src/main/kotlin/org/javacs/kt/Server.kt similarity index 86% rename from server/src/main/kotlin/org/javacs/kt/KotlinLanguageServer.kt rename to server/src/main/kotlin/org/javacs/kt/Server.kt index e8da0ff99..dc4a70a78 100644 --- a/server/src/main/kotlin/org/javacs/kt/KotlinLanguageServer.kt +++ b/server/src/main/kotlin/org/javacs/kt/Server.kt @@ -1,6 +1,25 @@ package org.javacs.kt -import org.eclipse.lsp4j.* +import java.io.Closeable +import java.nio.file.Paths +import java.util.concurrent.CompletableFuture +import java.util.concurrent.CompletableFuture.completedFuture +import kotlin.system.exitProcess +import org.eclipse.lsp4j.CompletionOptions +import org.eclipse.lsp4j.ExecuteCommandOptions +import org.eclipse.lsp4j.InitializeParams +import org.eclipse.lsp4j.InitializeResult +import org.eclipse.lsp4j.MessageParams +import org.eclipse.lsp4j.MessageType +import org.eclipse.lsp4j.RenameOptions +import org.eclipse.lsp4j.SemanticTokensWithRegistrationOptions +import org.eclipse.lsp4j.ServerCapabilities +import org.eclipse.lsp4j.ServerInfo +import org.eclipse.lsp4j.SignatureHelpOptions +import org.eclipse.lsp4j.TextDocumentSyncKind +import org.eclipse.lsp4j.WorkspaceFolder +import org.eclipse.lsp4j.WorkspaceFoldersOptions +import org.eclipse.lsp4j.WorkspaceServerCapabilities import org.eclipse.lsp4j.jsonrpc.messages.Either import org.eclipse.lsp4j.jsonrpc.services.JsonDelegate import org.eclipse.lsp4j.services.LanguageClient @@ -9,20 +28,18 @@ import org.eclipse.lsp4j.services.LanguageServer import org.eclipse.lsp4j.services.NotebookDocumentService import org.javacs.kt.command.ALL_COMMANDS import org.javacs.kt.database.DatabaseService +import org.javacs.kt.externalsources.ClassContentProvider +import org.javacs.kt.externalsources.ClassPathSourceArchiveProvider +import org.javacs.kt.externalsources.CompositeSourceArchiveProvider +import org.javacs.kt.externalsources.JdkSourceArchiveProvider import org.javacs.kt.progress.LanguageClientProgress import org.javacs.kt.progress.Progress import org.javacs.kt.semantictokens.semanticTokensLegend import org.javacs.kt.util.AsyncExecutor import org.javacs.kt.util.TemporaryDirectory import org.javacs.kt.util.parseURI -import org.javacs.kt.externalsources.* -import org.javacs.kt.index.SymbolIndex -import java.io.Closeable -import java.nio.file.Paths -import java.util.concurrent.CompletableFuture -import java.util.concurrent.CompletableFuture.completedFuture -class KotlinLanguageServer( +class Server( val config: Configuration = Configuration() ) : LanguageServer, LanguageClientAware, Closeable { val databaseService = DatabaseService() @@ -39,7 +56,7 @@ class KotlinLanguageServer( private lateinit var client: LanguageClient - private val async = AsyncExecutor() + private val asyncExecutor = AsyncExecutor(name = "server") private var progressFactory: Progress.Factory = Progress.Factory.None set(factory: Progress.Factory) { field = factory @@ -71,7 +88,7 @@ class KotlinLanguageServer( @JsonDelegate fun getProtocolExtensionService(): KotlinProtocolExtensions = protocolExtensions - override fun initialize(params: InitializeParams): CompletableFuture = async.compute { + override fun initialize(params: InitializeParams): CompletableFuture = asyncExecutor.compute { val serverCapabilities = ServerCapabilities() serverCapabilities.setTextDocumentSync(TextDocumentSyncKind.Incremental) serverCapabilities.workspace = WorkspaceServerCapabilities() @@ -108,14 +125,14 @@ class KotlinLanguageServer( serverCapabilities.renameProvider = Either.forRight(RenameOptions(false)) } + val progress = params.workDoneToken?.let { LanguageClientProgress("Workspace folders", it, client) } + @Suppress("DEPRECATION") val folders = params.workspaceFolders?.takeIf { it.isNotEmpty() } ?: params.rootUri?.let(::WorkspaceFolder)?.let(::listOf) ?: params.rootPath?.let(Paths::get)?.toUri()?.toString()?.let(::WorkspaceFolder)?.let(::listOf) ?: listOf() - val progress = params.workDoneToken?.let { LanguageClientProgress("Workspace folders", it, client) } - folders.forEachIndexed { i, folder -> LOG.info("Adding workspace folder {}", folder.name) val progressPrefix = "[${i + 1}/${folders.size}] ${folder.name ?: ""}" @@ -163,7 +180,7 @@ class KotlinLanguageServer( textDocumentService.close() classPath.close() tempDirectory.close() - async.shutdown(awaitTermination = true) + asyncExecutor.shutdown(awaitTermination = true) } override fun shutdown(): CompletableFuture { @@ -171,7 +188,9 @@ class KotlinLanguageServer( return completedFuture(null) } - override fun exit() {} + override fun exit() { + exitProcess(0) + } // Fixed in https://github.com/eclipse/lsp4j/commit/04b0c6112f0a94140e22b8b15bb5a90d5a0ed851 // Causes issue in lsp 0.15 diff --git a/server/src/main/kotlin/org/javacs/kt/SourceFiles.kt b/server/src/main/kotlin/org/javacs/kt/SourceFiles.kt index d7bb84968..13165dbb0 100644 --- a/server/src/main/kotlin/org/javacs/kt/SourceFiles.kt +++ b/server/src/main/kotlin/org/javacs/kt/SourceFiles.kt @@ -1,13 +1,11 @@ package org.javacs.kt import com.intellij.openapi.util.text.StringUtil.convertLineSeparators -import com.intellij.lang.java.JavaLanguage import com.intellij.lang.Language import org.jetbrains.kotlin.idea.KotlinLanguage import org.eclipse.lsp4j.TextDocumentContentChangeEvent import org.javacs.kt.util.KotlinLSException import org.javacs.kt.util.filePath -import org.javacs.kt.util.partitionAroundLast import org.javacs.kt.util.describeURIs import org.javacs.kt.util.describeURI import java.io.BufferedReader @@ -17,9 +15,7 @@ import java.io.IOException import java.io.FileNotFoundException import java.net.URI import java.nio.file.FileSystems -import java.nio.file.Files import java.nio.file.Path -import java.nio.file.Paths private class SourceVersion(val content: String, val version: Int, val language: Language?, val isTemporary: Boolean) diff --git a/server/src/main/kotlin/org/javacs/kt/SourcePath.kt b/server/src/main/kotlin/org/javacs/kt/SourcePath.kt index dff7e0d7e..fc65c6cfc 100644 --- a/server/src/main/kotlin/org/javacs/kt/SourcePath.kt +++ b/server/src/main/kotlin/org/javacs/kt/SourcePath.kt @@ -1,35 +1,35 @@ package org.javacs.kt -import org.javacs.kt.compiler.CompilationKind +import com.intellij.lang.Language +import java.net.URI +import java.nio.file.Path +import java.nio.file.Paths +import java.util.concurrent.locks.ReentrantLock +import kotlin.concurrent.withLock +import org.javacs.kt.compiler.CompilationType +import org.javacs.kt.database.DatabaseService +import org.javacs.kt.index.SymbolIndex +import org.javacs.kt.progress.Progress import org.javacs.kt.util.AsyncExecutor +import org.javacs.kt.util.describeURI import org.javacs.kt.util.fileExtension import org.javacs.kt.util.filePath -import org.javacs.kt.util.describeURI -import org.javacs.kt.index.SymbolIndex -import org.javacs.kt.progress.Progress -import com.intellij.lang.Language -import org.javacs.kt.database.DatabaseService import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.CompositeBindingContext import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter -import kotlin.concurrent.withLock -import java.nio.file.Path -import java.nio.file.Paths -import java.net.URI -import java.util.concurrent.locks.ReentrantLock class SourcePath( private val cp: CompilerClassPath, private val contentProvider: URIContentProvider, private val indexingConfig: IndexingConfiguration, - private val databaseService: DatabaseService + databaseService: DatabaseService, ) { private val files = mutableMapOf() private val parseDataWriteLock = ReentrantLock() - private val indexAsync = AsyncExecutor() + private val asyncExecutor = AsyncExecutor(name = "Indexer") var indexEnabled: Boolean by indexingConfig::enabled val index = SymbolIndex(databaseService) @@ -53,11 +53,15 @@ class SourcePath( val isTemporary: Boolean = false, // A temporary source file will not be returned by .all() var lastSavedFile: KtFile? = null, ) { - val extension: String? = uri.fileExtension ?: "kt" // TODO: Use language?.associatedFileType?.defaultExtension again + val extension: String = + uri.fileExtension + ?: "kt" // TODO: Use language?.associatedFileType?.defaultExtension again val isScript: Boolean = extension == "kts" - val kind: CompilationKind = - if (path?.fileName?.toString()?.endsWith(".gradle.kts") ?: false) CompilationKind.BUILD_SCRIPT - else CompilationKind.DEFAULT + + val kind: CompilationType = + if (path?.fileName?.toString()?.endsWith(".gradle.kts") == true) + CompilationType.BUILD_SCRIPT + else CompilationType.DEFAULT fun put(newContent: String) { content = newContent @@ -72,7 +76,12 @@ class SourcePath( fun parse() { // TODO: Create PsiFile using the stored language instead - parsed = cp.compiler.createKtFile(content, path ?: Paths.get("sourceFile.virtual.$extension"), kind) + parsed = + cp.compiler.createKtFile( + content, + path ?: Paths.get("sourceFile.virtual.$extension"), + kind, + ) } fun parseIfChanged() { @@ -115,25 +124,48 @@ class SourcePath( } fun prepareCompiledFile(): CompiledFile = - parseIfChanged().apply { compileIfNull() }.let { doPrepareCompiledFile() } + parseIfChanged().apply { compileIfNull() }.let { doPrepareCompiledFile() } private fun doPrepareCompiledFile(): CompiledFile = - CompiledFile(content, compiledFile!!, compiledContext!!, module!!, allIncludingThis(), cp, isScript, kind) - - private fun allIncludingThis(): Collection = parseIfChanged().let { - if (isTemporary) (all().asSequence() + sequenceOf(parsed!!)).toList() - else all() - } + CompiledFile( + content, + compiledFile!!, + compiledContext!!, + module!!, + allIncludingThis(), + cp, + isScript, + kind, + ) + + private fun allIncludingThis(): Collection = + parseIfChanged().let { + if (isTemporary) (all().asSequence() + sequenceOf(parsed!!)).toList() else all() + } // Creates a shallow copy - fun clone(): SourceFile = SourceFile(uri, content, path, parsed, compiledFile, compiledContext, module, language, isTemporary) + fun clone(): SourceFile = + SourceFile( + uri, + content, + path, + parsed, + compiledFile, + compiledContext, + module, + language, + isTemporary, + ) } private fun sourceFile(uri: URI): SourceFile { if (uri !in files) { // Fallback solution, usually *all* source files // should be added/opened through SourceFiles - LOG.warn("Requested source file {} is not on source path, this is most likely a bug. Adding it now temporarily...", describeURI(uri)) + LOG.warn( + "Requested source file {} is not on source path, this is most likely a bug. Adding it now temporarily...", + describeURI(uri), + ) put(uri, contentProvider.contentOf(uri), null, temporary = true) } return files[uri]!! @@ -171,46 +203,39 @@ class SourcePath( files.remove(uri) } - /** - * Get the latest content of a file - */ + /** Get the latest content of a file */ fun content(uri: URI): String = sourceFile(uri).content fun parsedFile(uri: URI): KtFile = sourceFile(uri).apply { parseIfChanged() }.parsed!! - /** - * Compile the latest version of a file - */ + /** Compile the latest version of a file */ fun currentVersion(uri: URI): CompiledFile = - sourceFile(uri).apply { compileIfChanged() }.prepareCompiledFile() + sourceFile(uri).apply { compileIfChanged() }.prepareCompiledFile() - /** - * Return whatever is the most-recent already-compiled version of `file` - */ - fun latestCompiledVersion(uri: URI): CompiledFile = - sourceFile(uri).prepareCompiledFile() + /** Return whatever is the most-recent already-compiled version of `file` */ + fun latestCompiledVersion(uri: URI): CompiledFile = sourceFile(uri).prepareCompiledFile() - /** - * Compile changed files - */ + /** Compile changed files */ fun compileFiles(all: Collection): BindingContext { // Figure out what has changed val sources = all.map { files[it]!! } val allChanged = sources.filter { it.content != it.compiledFile?.text } - val (changedBuildScripts, changedSources) = allChanged.partition { it.kind == CompilationKind.BUILD_SCRIPT } + val (changedBuildScripts, changedSources) = + allChanged.partition { it.kind == CompilationType.BUILD_SCRIPT } // Compile changed files - fun compileAndUpdate(changed: List, kind: CompilationKind): BindingContext? { + fun compileAndUpdate(changed: List, kind: CompilationType): BindingContext? { if (changed.isEmpty()) return null // Get clones of the old files, so we can remove the old declarations from the index - val oldFiles = changed.mapNotNull { - if (it.compiledFile?.text != it.content || it.parsed?.text != it.content) { - it.clone() - } else { - null + val oldFiles = + changed.mapNotNull { + if (it.compiledFile?.text != it.content || it.parsed?.text != it.content) { + it.clone() + } else { + null + } } - } // Parse the files that have changed val parse = changed.associateWith { it.apply { parseIfChanged() }.parsed!! } @@ -224,7 +249,7 @@ class SourcePath( for ((f, parsed) in parse) { parseDataWriteLock.withLock { if (f.parsed == parsed) { - //only updated if the parsed file didn't change: + // only updated if the parsed file didn't change: f.compiledFile = parsed f.compiledContext = context f.module = module @@ -233,26 +258,30 @@ class SourcePath( } // Only index normal files, not build files - if (kind == CompilationKind.DEFAULT) { + if (kind == CompilationType.DEFAULT) { refreshWorkspaceIndexes(oldFiles, parse.keys.toList()) } return context } - val buildScriptsContext = compileAndUpdate(changedBuildScripts, CompilationKind.BUILD_SCRIPT) - val sourcesContext = compileAndUpdate(changedSources, CompilationKind.DEFAULT) + val buildScriptsContext = + compileAndUpdate(changedBuildScripts, CompilationType.BUILD_SCRIPT) + val sourcesContext = compileAndUpdate(changedSources, CompilationType.DEFAULT) // Combine with past compilations - val same = sources - allChanged - val combined = listOf(buildScriptsContext, sourcesContext).filterNotNull() + same.map { it.compiledContext!! } + val same = sources - allChanged.toSet() + val combined = + listOfNotNull(buildScriptsContext, sourcesContext) + same.map { it.compiledContext!! } return CompositeBindingContext.create(combined) } fun compileAllFiles() { - // TODO: Investigate the possibility of compiling all files at once, instead of iterating here - // At the moment, compiling all files at once sometimes leads to an internal error from the TopDownAnalyzer + // TODO: Investigate the possibility of compiling all files at once, instead of iterating + // here + // At the moment, compiling all files at once sometimes leads to an internal error from the + // TopDownAnalyzer files.keys.forEach { // If one of the files fails to compile, we compile the others anyway try { @@ -264,17 +293,23 @@ class SourcePath( } /** - * Saves a file. This generates code for the file and deletes previously generated code for this file. + * Saves a file. This generates code for the file and deletes previously generated code for this + * file. */ fun save(uri: URI) { files[uri]?.let { if (!it.isScript) { - // If the code generation fails for some reason, we generate code for the other files anyway + // If the code generation fails for some reason, we generate code for the other + // files anyway try { cp.compiler.removeGeneratedCode(listOfNotNull(it.lastSavedFile)) it.module?.let { module -> it.compiledContext?.let { context -> - cp.compiler.generateCode(module, context, listOfNotNull(it.compiledFile)) + cp.compiler.generateCode( + module, + context, + listOfNotNull(it.compiledFile), + ) it.lastSavedFile = it.compiledFile } } @@ -299,45 +334,53 @@ class SourcePath( } /** - * Refreshes the indexes. If already done, refreshes only the declarations in the files that were changed. + * Refreshes the indexes. If already done, refreshes only the declarations in the files that + * were changed. */ - private fun refreshWorkspaceIndexes(oldFiles: List, newFiles: List) = indexAsync.execute { - if (indexEnabled) { - val oldDeclarations = getDeclarationDescriptors(oldFiles) - val newDeclarations = getDeclarationDescriptors(newFiles) - - // Index the new declarations in the Kotlin source files that were just compiled, removing the old ones - index.updateIndexes(oldDeclarations, newDeclarations) + private fun refreshWorkspaceIndexes(oldFiles: List, newFiles: List) = + asyncExecutor.execute { + if (indexEnabled) { + val oldDeclarations = getDeclarationDescriptors(oldFiles) + val newDeclarations = getDeclarationDescriptors(newFiles) + + // Index the new declarations in the Kotlin source files that were just compiled, + // removing the old ones + index.updateIndexes(oldDeclarations, newDeclarations) + } } - } /** - * Refreshes the indexes. If already done, refreshes only the declarations in the files that were changed. + * Refreshes the indexes. If already done, refreshes only the declarations in the files that + * were changed. */ - private fun refreshDependencyIndexes(module: ModuleDescriptor) = indexAsync.execute { - if (indexEnabled) { - val declarations = getDeclarationDescriptors(files.values) - index.refresh(module, declarations) + private fun refreshDependencyIndexes(module: ModuleDescriptor) = + asyncExecutor.execute { + if (indexEnabled) { + val declarations = getDeclarationDescriptors(files.values) + index.refresh(module, declarations) + } } - } // Gets all the declaration descriptors for the collection of files private fun getDeclarationDescriptors(files: Collection) = - files.flatMap { file -> - val compiledFile = file.compiledFile ?: file.parsed - val module = file.module - if (compiledFile != null && module != null) { - module.getPackage(compiledFile.packageFqName).memberScope.getContributedDescriptors( - DescriptorKindFilter.ALL - ) { name -> compiledFile.declarations.map { it.name }.contains(name.toString()) } - } else { - listOf() + files + .flatMap { file -> + val compiledFile = file.compiledFile ?: file.parsed + val module = file.module + if (compiledFile != null && module != null) { + module + .getPackage(compiledFile.packageFqName) + .memberScope + .getContributedDescriptors(DescriptorKindFilter.ALL) { name -> + compiledFile.declarations.map { it.name }.contains(name.toString()) + } + } else { + listOf() + } } - }.asSequence() + .asSequence() - /** - * Recompiles all source files that are initialized. - */ + /** Recompiles all source files that are initialized. */ fun refresh() { val initialized = files.values.any { it.parsed != null } if (initialized) { @@ -347,11 +390,9 @@ class SourcePath( } } - /** - * Get parsed trees for all .kt files on source path - */ + /** Get parsed trees for all .kt files on source path */ fun all(includeHidden: Boolean = false): Collection = - files.values - .filter { includeHidden || !it.isTemporary } - .map { it.apply { parseIfChanged() }.parsed!! } + files.values + .filter { includeHidden || !it.isTemporary } + .map { it.apply { parseIfChanged() }.parsed!! } } diff --git a/server/src/main/kotlin/org/javacs/kt/codeaction/quickfix/AddMissingImportsQuickFix.kt b/server/src/main/kotlin/org/javacs/kt/codeaction/quickfix/AddMissingImportsQuickFix.kt index 1eb9462e0..b800e2af2 100644 --- a/server/src/main/kotlin/org/javacs/kt/codeaction/quickfix/AddMissingImportsQuickFix.kt +++ b/server/src/main/kotlin/org/javacs/kt/codeaction/quickfix/AddMissingImportsQuickFix.kt @@ -4,19 +4,17 @@ import org.eclipse.lsp4j.* import org.eclipse.lsp4j.jsonrpc.messages.Either import org.jetbrains.kotlin.psi.KtFile import org.javacs.kt.CompiledFile -import org.javacs.kt.LOG import org.javacs.kt.index.SymbolIndex import org.javacs.kt.index.Symbol import org.javacs.kt.position.offset import org.javacs.kt.util.toPath -import org.javacs.kt.codeaction.quickfix.diagnosticMatch import org.javacs.kt.imports.getImportTextEditEntry class AddMissingImportsQuickFix: QuickFix { override fun compute(file: CompiledFile, index: SymbolIndex, range: Range, diagnostics: List): List> { val uri = file.parse.toPath().toUri().toString() - val unresolvedReferences = getUnresolvedReferencesFromDiagnostics(diagnostics) - + val unresolvedReferences = getUnresolvedReferencesFromDiagnostics(diagnostics) + return unresolvedReferences.flatMap { diagnostic -> val diagnosticRange = diagnostic.range val startCursor = offset(file.content, diagnosticRange.start) @@ -25,11 +23,11 @@ class AddMissingImportsQuickFix: QuickFix { getImportAlternatives(symbolName, file.parse, index).map { (importStr, edit) -> val codeAction = CodeAction() - codeAction.title = "Import ${importStr}" + codeAction.title = "Import $importStr" codeAction.kind = CodeActionKind.QuickFix codeAction.diagnostics = listOf(diagnostic) codeAction.edit = WorkspaceEdit(mapOf(uri to listOf(edit))) - + Either.forRight(codeAction) } } @@ -43,7 +41,7 @@ class AddMissingImportsQuickFix: QuickFix { private fun getImportAlternatives(symbolName: String, file: KtFile, index: SymbolIndex): List> { // wildcard matcher to empty string, because we only want to match exactly the symbol itself, not anything extra val queryResult = index.query(symbolName, suffix = "") - + return queryResult .filter { it.kind != Symbol.Kind.MODULE && diff --git a/server/src/main/kotlin/org/javacs/kt/codeaction/quickfix/ImplementAbstractMembersQuickFix.kt b/server/src/main/kotlin/org/javacs/kt/codeaction/quickfix/ImplementAbstractMembersQuickFix.kt index e4b0a6b11..e425003f1 100644 --- a/server/src/main/kotlin/org/javacs/kt/codeaction/quickfix/ImplementAbstractMembersQuickFix.kt +++ b/server/src/main/kotlin/org/javacs/kt/codeaction/quickfix/ImplementAbstractMembersQuickFix.kt @@ -4,9 +4,6 @@ import org.eclipse.lsp4j.* import org.eclipse.lsp4j.jsonrpc.messages.Either import org.javacs.kt.CompiledFile import org.javacs.kt.index.SymbolIndex -import org.javacs.kt.position.offset -import org.javacs.kt.position.position -import org.javacs.kt.util.toPath import org.javacs.kt.overridemembers.createFunctionStub import org.javacs.kt.overridemembers.createVariableStub import org.javacs.kt.overridemembers.getClassDescriptor @@ -15,40 +12,31 @@ import org.javacs.kt.overridemembers.getNewMembersStartPosition import org.javacs.kt.overridemembers.getSuperClassTypeProjections import org.javacs.kt.overridemembers.hasNoBody import org.javacs.kt.overridemembers.overridesDeclaration -import org.jetbrains.kotlin.descriptors.ClassDescriptor -import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.javacs.kt.position.offset +import org.javacs.kt.util.toPath import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.PropertyDescriptor import org.jetbrains.kotlin.descriptors.isInterface -import org.jetbrains.kotlin.descriptors.Modality -import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi -import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.psi.KtClass -import org.jetbrains.kotlin.psi.KtDeclaration -import org.jetbrains.kotlin.psi.KtNamedFunction -import org.jetbrains.kotlin.psi.KtSimpleNameExpression -import org.jetbrains.kotlin.psi.KtSuperTypeListEntry -import org.jetbrains.kotlin.psi.KtTypeArgumentList -import org.jetbrains.kotlin.psi.KtTypeReference -import org.jetbrains.kotlin.psi.psiUtil.containingClass -import org.jetbrains.kotlin.psi.psiUtil.endOffset -import org.jetbrains.kotlin.psi.psiUtil.isAbstract import org.jetbrains.kotlin.psi.psiUtil.startOffset import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics -import org.jetbrains.kotlin.types.KotlinType -import org.jetbrains.kotlin.types.TypeProjection -import org.jetbrains.kotlin.types.typeUtil.asTypeProjection class ImplementAbstractMembersQuickFix : QuickFix { - override fun compute(file: CompiledFile, index: SymbolIndex, range: Range, diagnostics: List): List> { + override fun compute( + file: CompiledFile, + index: SymbolIndex, + range: Range, + diagnostics: List, + ): List> { val diagnostic = findDiagnosticMatch(diagnostics, range) val startCursor = offset(file.content, range.start) val endCursor = offset(file.content, range.end) val kotlinDiagnostics = file.compile.diagnostics - - // If the client side and the server side diagnostics contain a valid diagnostic for this range. + + // If the client side and the server side diagnostics contain a valid diagnostic for this + // range. if (diagnostic != null && anyDiagnosticMatch(kotlinDiagnostics, startCursor, endCursor)) { // Get the class with the missing members val kotlinClass = file.parseAtPoint(startCursor) @@ -62,14 +50,30 @@ class ImplementAbstractMembersQuickFix : QuickFix { // Get the location where the new code will be placed val newMembersStartPosition = getNewMembersStartPosition(file, kotlinClass) - val bodyAppendBeginning = listOf(TextEdit(Range(newMembersStartPosition, newMembersStartPosition), "{")).takeIf { kotlinClass.hasNoBody() } ?: emptyList() - val bodyAppendEnd = listOf(TextEdit(Range(newMembersStartPosition, newMembersStartPosition), System.lineSeparator() + "}")).takeIf { kotlinClass.hasNoBody() } ?: emptyList() + val bodyAppendBeginning = + listOf(TextEdit(Range(newMembersStartPosition, newMembersStartPosition), "{")) + .takeIf { kotlinClass.hasNoBody() } ?: emptyList() + val bodyAppendEnd = + listOf( + TextEdit( + Range(newMembersStartPosition, newMembersStartPosition), + System.lineSeparator() + "}", + ) + ) + .takeIf { kotlinClass.hasNoBody() } ?: emptyList() - val textEdits = bodyAppendBeginning + membersToImplement.map { - // We leave two new lines before the member is inserted - val newText = System.lineSeparator() + System.lineSeparator() + padding + it - TextEdit(Range(newMembersStartPosition, newMembersStartPosition), newText) - } + bodyAppendEnd + val textEdits = + bodyAppendBeginning + + membersToImplement.map { + // We leave two new lines before the member is inserted + val newText = + System.lineSeparator() + System.lineSeparator() + padding + it + TextEdit( + Range(newMembersStartPosition, newMembersStartPosition), + newText, + ) + } + + bodyAppendEnd val codeAction = CodeAction() codeAction.edit = WorkspaceEdit(mapOf(uri to textEdits)) @@ -81,36 +85,70 @@ class ImplementAbstractMembersQuickFix : QuickFix { } return listOf() } -} -fun findDiagnosticMatch(diagnostics: List, range: Range) = - diagnostics.find { diagnosticMatch(it, range, hashSetOf("ABSTRACT_MEMBER_NOT_IMPLEMENTED", "ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED")) } + private fun findDiagnosticMatch(diagnostics: List, range: Range) = + diagnostics.find { + diagnosticMatch( + it, + range, + hashSetOf( + "ABSTRACT_MEMBER_NOT_IMPLEMENTED", + "ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED", + ), + ) + } + + private fun anyDiagnosticMatch(diagnostics: Diagnostics, startCursor: Int, endCursor: Int) = + diagnostics.any { + diagnosticMatch( + it, + startCursor, + endCursor, + hashSetOf( + "ABSTRACT_MEMBER_NOT_IMPLEMENTED", + "ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED", + ), + ) + } -private fun anyDiagnosticMatch(diagnostics: Diagnostics, startCursor: Int, endCursor: Int) = - diagnostics.any { diagnosticMatch(it, startCursor, endCursor, hashSetOf("ABSTRACT_MEMBER_NOT_IMPLEMENTED", "ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED")) } + private fun getAbstractMembersStubs(file: CompiledFile, kotlinClass: KtClass) = + // For each of the super types used by this class + kotlinClass.superTypeListEntries + .mapNotNull { + // Find the definition of this super type + val referenceAtPoint = file.referenceExpressionAtPoint(it.startOffset) + val descriptor = referenceAtPoint?.second -private fun getAbstractMembersStubs(file: CompiledFile, kotlinClass: KtClass) = - // For each of the super types used by this class - kotlinClass.superTypeListEntries.mapNotNull { - // Find the definition of this super type - val referenceAtPoint = file.referenceExpressionAtPoint(it.startOffset) - val descriptor = referenceAtPoint?.second + val classDescriptor = getClassDescriptor(descriptor) - val classDescriptor = getClassDescriptor(descriptor) - - // If the super class is abstract or an interface - if (null != classDescriptor && (classDescriptor.kind.isInterface || classDescriptor.modality == Modality.ABSTRACT)) { - val superClassTypeArguments = getSuperClassTypeProjections(file, it) - classDescriptor.getMemberScope(superClassTypeArguments).getContributedDescriptors().filter { classMember -> - (classMember is FunctionDescriptor && classMember.modality == Modality.ABSTRACT && !overridesDeclaration(kotlinClass, classMember)) || (classMember is PropertyDescriptor && classMember.modality == Modality.ABSTRACT && !overridesDeclaration(kotlinClass, classMember)) - }.mapNotNull { member -> - when (member) { - is FunctionDescriptor -> createFunctionStub(member) - is PropertyDescriptor -> createVariableStub(member) - else -> null + // If the super class is abstract or an interface + if ( + null != classDescriptor && + (classDescriptor.kind.isInterface || + classDescriptor.modality == Modality.ABSTRACT) + ) { + val superClassTypeArguments = getSuperClassTypeProjections(file, it) + classDescriptor + .getMemberScope(superClassTypeArguments) + .getContributedDescriptors() + .filter { classMember -> + (classMember is FunctionDescriptor && + classMember.modality == Modality.ABSTRACT && + !overridesDeclaration(kotlinClass, classMember)) || + (classMember is PropertyDescriptor && + classMember.modality == Modality.ABSTRACT && + !overridesDeclaration(kotlinClass, classMember)) + } + .mapNotNull { member -> + when (member) { + is FunctionDescriptor -> createFunctionStub(member) + is PropertyDescriptor -> createVariableStub(member) + else -> null + } + } + } else { + null } } - } else { - null - } - }.flatten() + .flatten() +} diff --git a/server/src/main/kotlin/org/javacs/kt/codeaction/quickfix/QuickFix.kt b/server/src/main/kotlin/org/javacs/kt/codeaction/quickfix/QuickFix.kt index 89526bb0a..adb60be5c 100644 --- a/server/src/main/kotlin/org/javacs/kt/codeaction/quickfix/QuickFix.kt +++ b/server/src/main/kotlin/org/javacs/kt/codeaction/quickfix/QuickFix.kt @@ -8,10 +8,9 @@ import org.eclipse.lsp4j.jsonrpc.messages.Either import org.javacs.kt.CompiledFile import org.javacs.kt.index.SymbolIndex import org.javacs.kt.util.isSubrangeOf -import org.jetbrains.kotlin.resolve.diagnostics.Diagnostics import org.jetbrains.kotlin.diagnostics.Diagnostic as KotlinDiagnostic -interface QuickFix { +fun interface QuickFix { // Computes the quickfix. Return empty list if the quickfix is not valid or no alternatives exist. fun compute(file: CompiledFile, index: SymbolIndex, range: Range, diagnostics: List): List> } @@ -21,9 +20,3 @@ fun diagnosticMatch(diagnostic: Diagnostic, range: Range, diagnosticTypes: Set): Boolean = diagnostic.textRanges.any { it.startOffset <= startCursor && it.endOffset >= endCursor } && diagnosticTypes.contains(diagnostic.factory.name) - -fun findDiagnosticMatch(diagnostics: List, range: Range, diagnosticTypes: Set) = - diagnostics.find { diagnosticMatch(it, range, diagnosticTypes) } - -fun anyDiagnosticMatch(diagnostics: Diagnostics, startCursor: Int, endCursor: Int, diagnosticTypes: Set) = - diagnostics.any { diagnosticMatch(it, startCursor, endCursor, diagnosticTypes) } diff --git a/server/src/main/kotlin/org/javacs/kt/compiler/CompilationEnvironment.kt b/server/src/main/kotlin/org/javacs/kt/compiler/CompilationEnvironment.kt new file mode 100644 index 000000000..26ae3855f --- /dev/null +++ b/server/src/main/kotlin/org/javacs/kt/compiler/CompilationEnvironment.kt @@ -0,0 +1,424 @@ +@file:Suppress("DEPRECATION") + +package org.javacs.kt.compiler + +import com.intellij.openapi.util.Disposer +import java.io.Closeable +import java.io.File +import java.net.URLClassLoader +import java.nio.file.Path +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.host.ScriptingHostConfiguration +import kotlin.script.experimental.host.configurationDependencies +import kotlin.script.experimental.jvm.JvmDependency +import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration +import org.javacs.kt.CompilerConfiguration +import org.javacs.kt.LOG +import org.javacs.kt.ScriptsConfiguration +import org.javacs.kt.util.LoggingMessageCollector +import org.jetbrains.kotlin.cli.jvm.compiler.CliBindingTrace +import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM +import org.jetbrains.kotlin.cli.jvm.config.addJavaSourceRoots +import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots +import org.jetbrains.kotlin.cli.jvm.config.configureJdkClasspathRoots +import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar +import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar +import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi +import org.jetbrains.kotlin.config.ApiVersion +import org.jetbrains.kotlin.config.CommonConfigurationKeys +import org.jetbrains.kotlin.config.CompilerConfiguration as CompilerConfigurationApi +import org.jetbrains.kotlin.config.JVMConfigurationKeys +import org.jetbrains.kotlin.config.JvmTarget +import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.config.LanguageVersion +import org.jetbrains.kotlin.config.LanguageVersionSettingsImpl +import org.jetbrains.kotlin.container.ComponentProvider +import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor +import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil +import org.jetbrains.kotlin.psi.KtFile +import org.jetbrains.kotlin.psi.KtPsiFactory +import org.jetbrains.kotlin.resolve.BindingTraceContext +import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory +import org.jetbrains.kotlin.samWithReceiver.CliSamWithReceiverComponentContributor +import org.jetbrains.kotlin.scripting.compiler.plugin.ScriptingCompilerConfigurationComponentRegistrar +import org.jetbrains.kotlin.scripting.compiler.plugin.ScriptingK2CompilerPluginRegistrar +import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys +import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition +import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition +import org.jetbrains.kotlin.scripting.definitions.getEnvironment +import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate + +/** + * Kotlin compiler APIs used to parse, analyze and compile + * files and expressions. + */ +internal class CompilationEnvironment( + javaSourcePath: Set, + classPath: Set, + scriptsConfig: ScriptsConfiguration +) : Closeable { + private val disposable = Disposer.newDisposable() + + @OptIn(ExperimentalCompilerApi::class) + val environment: KotlinCoreEnvironment = KotlinCoreEnvironment.createForProduction( + projectDisposable = disposable, + // Not to be confused with the CompilerConfiguration in the language server Configuration + configuration = CompilerConfigurationApi().apply { + val langFeatures = mutableMapOf() + for (langFeature in LanguageFeature.entries) { + langFeatures[langFeature] = LanguageFeature.State.ENABLED + } + val languageVersionSettings = LanguageVersionSettingsImpl( + LanguageVersion.LATEST_STABLE, + ApiVersion.createByLanguageVersion(LanguageVersion.LATEST_STABLE), + emptyMap(), + langFeatures + ) + + put(CommonConfigurationKeys.MODULE_NAME, JvmProtoBufUtil.DEFAULT_MODULE_NAME) + put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, languageVersionSettings) + put(CommonConfigurationKeys.MESSAGE_COLLECTOR_KEY, LoggingMessageCollector) + add(ComponentRegistrar.PLUGIN_COMPONENT_REGISTRARS, ScriptingCompilerConfigurationComponentRegistrar()) + add(CompilerPluginRegistrar.COMPILER_PLUGIN_REGISTRARS, ScriptingK2CompilerPluginRegistrar()) + put(JVMConfigurationKeys.USE_PSI_CLASS_FILES_READING, true) + + // configure jvm runtime classpaths + configureJdkClasspathRoots() + + // Kotlin 1.8.20 requires us to specify the JDK home, otherwise java.* classes won't resolve + // See https://github.com/JetBrains/kotlin-compiler-server/pull/626 + val jdkHome = File(System.getProperty("java.home")) + put(JVMConfigurationKeys.JDK_HOME, jdkHome) + + addJvmClasspathRoots(classPath.map { it.toFile() }) + addJavaSourceRoots(javaSourcePath.map { it.toFile() }) + + if (scriptsConfig.enabled) { + // Setup script templates (e.g. used by Gradle's Kotlin DSL) + val scriptDefinitions: MutableList = + mutableListOf(ScriptDefinition.getDefault(defaultJvmScriptingHostConfiguration)) + + val foundDSLDependency = classPath.any { Regex("^gradle-(?:kotlin-dsl|core).*\\.jar$").matches(it.fileName.toString()) } + if (scriptsConfig.buildScriptsEnabled && foundDSLDependency) { + LOG.info("Configuring Kotlin DSL script templates...") + + val scriptTemplates = listOf( + "org.gradle.kotlin.dsl.KotlinInitScript", + "org.gradle.kotlin.dsl.KotlinSettingsScript", + "org.gradle.kotlin.dsl.KotlinBuildScript" + ) + + try { + // Load template classes + val scriptClassLoader = URLClassLoader(classPath.map { it.toUri().toURL() }.toTypedArray()) + val fileClassPath = classPath.map { it.toFile() } + val scriptHostConfig = ScriptingHostConfiguration(defaultJvmScriptingHostConfiguration) { + configurationDependencies(JvmDependency(fileClassPath)) + } + // TODO: KotlinScriptDefinition will soon be deprecated, use + // ScriptDefinition.compilationConfiguration and its defaultImports instead + // of KotlinScriptDefinition.dependencyResolver + // TODO: Use ScriptDefinition.FromLegacyTemplate directly if possible + // scriptDefinitions = scriptTemplates.map { ScriptDefinition.FromLegacyTemplate(scriptHostConfig, scriptClassLoader.loadClass(it).kotlin) } + scriptDefinitions.addAll(scriptTemplates.map { + ScriptDefinition.FromLegacy( + scriptHostConfig, + object : KotlinScriptDefinitionFromAnnotatedTemplate( + scriptClassLoader.loadClass(it).kotlin, + scriptHostConfig[ScriptingHostConfiguration.getEnvironment]?.invoke() + ) { + override fun isScript(fileName: String): Boolean { + // The pattern for KotlinSettingsScript doesn't seem to work well, so kinda "forcing it" for settings.gradle.kts files + if (this.template.simpleName == "KotlinSettingsScript" && fileName.endsWith("settings.gradle.kts")) { + return true + } + + return super.isScript(fileName) + } + + override val dependencyResolver: DependenciesResolver = + object : DependenciesResolver { + override fun resolve( + scriptContents: ScriptContents, + environment: Environment + ) = DependenciesResolver.ResolveResult.Success( + ScriptDependencies( + imports = listOf( + "org.gradle.kotlin.dsl.*", + "org.gradle.kotlin.dsl.plugins.dsl.*", + "org.gradle.*", + "org.gradle.api.*", + "org.gradle.api.artifacts.*", + "org.gradle.api.artifacts.component.*", + "org.gradle.api.artifacts.dsl.*", + "org.gradle.api.artifacts.ivy.*", + "org.gradle.api.artifacts.maven.*", + "org.gradle.api.artifacts.query.*", + "org.gradle.api.artifacts.repositories.*", + "org.gradle.api.artifacts.result.*", + "org.gradle.api.artifacts.transform.*", + "org.gradle.api.artifacts.type.*", + "org.gradle.api.artifacts.verification.*", + "org.gradle.api.attributes.*", + "org.gradle.api.attributes.java.*", + "org.gradle.api.capabilities.*", + "org.gradle.api.component.*", + "org.gradle.api.credentials.*", + "org.gradle.api.distribution.*", + "org.gradle.api.distribution.plugins.*", + "org.gradle.api.execution.*", + "org.gradle.api.file.*", + "org.gradle.api.initialization.*", + "org.gradle.api.initialization.definition.*", + "org.gradle.api.initialization.dsl.*", + "org.gradle.api.invocation.*", + "org.gradle.api.java.archives.*", + "org.gradle.api.jvm.*", + "org.gradle.api.logging.*", + "org.gradle.api.logging.configuration.*", + "org.gradle.api.model.*", + "org.gradle.api.plugins.*", + "org.gradle.api.plugins.antlr.*", + "org.gradle.api.plugins.quality.*", + "org.gradle.api.plugins.scala.*", + "org.gradle.api.provider.*", + "org.gradle.api.publish.*", + "org.gradle.api.publish.ivy.*", + "org.gradle.api.publish.ivy.plugins.*", + "org.gradle.api.publish.ivy.tasks.*", + "org.gradle.api.publish.maven.*", + "org.gradle.api.publish.maven.plugins.*", + "org.gradle.api.publish.maven.tasks.*", + "org.gradle.api.publish.plugins.*", + "org.gradle.api.publish.tasks.*", + "org.gradle.api.reflect.*", + "org.gradle.api.reporting.*", + "org.gradle.api.reporting.components.*", + "org.gradle.api.reporting.dependencies.*", + "org.gradle.api.reporting.dependents.*", + "org.gradle.api.reporting.model.*", + "org.gradle.api.reporting.plugins.*", + "org.gradle.api.resources.*", + "org.gradle.api.services.*", + "org.gradle.api.specs.*", + "org.gradle.api.tasks.*", + "org.gradle.api.tasks.ant.*", + "org.gradle.api.tasks.application.*", + "org.gradle.api.tasks.bundling.*", + "org.gradle.api.tasks.compile.*", + "org.gradle.api.tasks.diagnostics.*", + "org.gradle.api.tasks.incremental.*", + "org.gradle.api.tasks.javadoc.*", + "org.gradle.api.tasks.options.*", + "org.gradle.api.tasks.scala.*", + "org.gradle.api.tasks.testing.*", + "org.gradle.api.tasks.testing.junit.*", + "org.gradle.api.tasks.testing.junitplatform.*", + "org.gradle.api.tasks.testing.testng.*", + "org.gradle.api.tasks.util.*", + "org.gradle.api.tasks.wrapper.*", + "org.gradle.authentication.*", + "org.gradle.authentication.aws.*", + "org.gradle.authentication.http.*", + "org.gradle.build.event.*", + "org.gradle.buildinit.plugins.*", + "org.gradle.buildinit.tasks.*", + "org.gradle.caching.*", + "org.gradle.caching.configuration.*", + "org.gradle.caching.http.*", + "org.gradle.caching.local.*", + "org.gradle.concurrent.*", + "org.gradle.external.javadoc.*", + "org.gradle.ide.visualstudio.*", + "org.gradle.ide.visualstudio.plugins.*", + "org.gradle.ide.visualstudio.tasks.*", + "org.gradle.ide.xcode.*", + "org.gradle.ide.xcode.plugins.*", + "org.gradle.ide.xcode.tasks.*", + "org.gradle.ivy.*", + "org.gradle.jvm.*", + "org.gradle.jvm.application.scripts.*", + "org.gradle.jvm.application.tasks.*", + "org.gradle.jvm.platform.*", + "org.gradle.jvm.plugins.*", + "org.gradle.jvm.tasks.*", + "org.gradle.jvm.tasks.api.*", + "org.gradle.jvm.test.*", + "org.gradle.jvm.toolchain.*", + "org.gradle.language.*", + "org.gradle.language.assembler.*", + "org.gradle.language.assembler.plugins.*", + "org.gradle.language.assembler.tasks.*", + "org.gradle.language.base.*", + "org.gradle.language.base.artifact.*", + "org.gradle.language.base.compile.*", + "org.gradle.language.base.plugins.*", + "org.gradle.language.base.sources.*", + "org.gradle.language.c.*", + "org.gradle.language.c.plugins.*", + "org.gradle.language.c.tasks.*", + "org.gradle.language.coffeescript.*", + "org.gradle.language.cpp.*", + "org.gradle.language.cpp.plugins.*", + "org.gradle.language.cpp.tasks.*", + "org.gradle.language.java.*", + "org.gradle.language.java.artifact.*", + "org.gradle.language.java.plugins.*", + "org.gradle.language.java.tasks.*", + "org.gradle.language.javascript.*", + "org.gradle.language.jvm.*", + "org.gradle.language.jvm.plugins.*", + "org.gradle.language.jvm.tasks.*", + "org.gradle.language.nativeplatform.*", + "org.gradle.language.nativeplatform.tasks.*", + "org.gradle.language.objectivec.*", + "org.gradle.language.objectivec.plugins.*", + "org.gradle.language.objectivec.tasks.*", + "org.gradle.language.objectivecpp.*", + "org.gradle.language.objectivecpp.plugins.*", + "org.gradle.language.objectivecpp.tasks.*", + "org.gradle.language.plugins.*", + "org.gradle.language.rc.*", + "org.gradle.language.rc.plugins.*", + "org.gradle.language.rc.tasks.*", + "org.gradle.language.routes.*", + "org.gradle.language.scala.*", + "org.gradle.language.scala.plugins.*", + "org.gradle.language.scala.tasks.*", + "org.gradle.language.scala.toolchain.*", + "org.gradle.language.swift.*", + "org.gradle.language.swift.plugins.*", + "org.gradle.language.swift.tasks.*", + "org.gradle.language.twirl.*", + "org.gradle.maven.*", + "org.gradle.model.*", + "org.gradle.nativeplatform.*", + "org.gradle.nativeplatform.platform.*", + "org.gradle.nativeplatform.plugins.*", + "org.gradle.nativeplatform.tasks.*", + "org.gradle.nativeplatform.test.*", + "org.gradle.nativeplatform.test.cpp.*", + "org.gradle.nativeplatform.test.cpp.plugins.*", + "org.gradle.nativeplatform.test.cunit.*", + "org.gradle.nativeplatform.test.cunit.plugins.*", + "org.gradle.nativeplatform.test.cunit.tasks.*", + "org.gradle.nativeplatform.test.googletest.*", + "org.gradle.nativeplatform.test.googletest.plugins.*", + "org.gradle.nativeplatform.test.plugins.*", + "org.gradle.nativeplatform.test.tasks.*", + "org.gradle.nativeplatform.test.xctest.*", + "org.gradle.nativeplatform.test.xctest.plugins.*", + "org.gradle.nativeplatform.test.xctest.tasks.*", + "org.gradle.nativeplatform.toolchain.*", + "org.gradle.nativeplatform.toolchain.plugins.*", + "org.gradle.normalization.*", + "org.gradle.platform.base.*", + "org.gradle.platform.base.binary.*", + "org.gradle.platform.base.component.*", + "org.gradle.platform.base.plugins.*", + "org.gradle.play.*", + "org.gradle.play.distribution.*", + "org.gradle.play.platform.*", + "org.gradle.play.plugins.*", + "org.gradle.play.plugins.ide.*", + "org.gradle.play.tasks.*", + "org.gradle.play.toolchain.*", + "org.gradle.plugin.devel.*", + "org.gradle.plugin.devel.plugins.*", + "org.gradle.plugin.devel.tasks.*", + "org.gradle.plugin.management.*", + "org.gradle.plugin.use.*", + "org.gradle.plugins.ear.*", + "org.gradle.plugins.ear.descriptor.*", + "org.gradle.plugins.ide.*", + "org.gradle.plugins.ide.api.*", + "org.gradle.plugins.ide.eclipse.*", + "org.gradle.plugins.ide.idea.*", + "org.gradle.plugins.javascript.base.*", + "org.gradle.plugins.javascript.coffeescript.*", + "org.gradle.plugins.javascript.envjs.*", + "org.gradle.plugins.javascript.envjs.browser.*", + "org.gradle.plugins.javascript.envjs.http.*", + "org.gradle.plugins.javascript.envjs.http.simple.*", + "org.gradle.plugins.javascript.jshint.*", + "org.gradle.plugins.javascript.rhino.*", + "org.gradle.plugins.signing.*", + "org.gradle.plugins.signing.signatory.*", + "org.gradle.plugins.signing.signatory.pgp.*", + "org.gradle.plugins.signing.type.*", + "org.gradle.plugins.signing.type.pgp.*", + "org.gradle.process.*", + "org.gradle.swiftpm.*", + "org.gradle.swiftpm.plugins.*", + "org.gradle.swiftpm.tasks.*", + "org.gradle.testing.base.*", + "org.gradle.testing.base.plugins.*", + "org.gradle.testing.jacoco.plugins.*", + "org.gradle.testing.jacoco.tasks.*", + "org.gradle.testing.jacoco.tasks.rules.*", + "org.gradle.testkit.runner.*", + "org.gradle.vcs.*", + "org.gradle.vcs.git.*", + "org.gradle.work.*", + "org.gradle.workers.*" + ) + ) + ) + } + }) + }) + } catch (e: Exception) { + LOG.error("Error while loading script template classes") + LOG.printStackTrace(e) + } + } + + LOG.info("Adding script definitions ${scriptDefinitions.map { it.asLegacyOrNull()?.template?.simpleName }}") + addAll(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS, scriptDefinitions) + } + }, + configFiles = EnvironmentConfigFiles.JVM_CONFIG_FILES + ) + private val parser: KtPsiFactory + + init { + // hacky way to support SamWithReceiverAnnotations for scripts + val scriptDefinitions: List = environment.configuration.getList(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS) + scriptDefinitions.takeIf { it.isNotEmpty() }?.let { + val annotations = scriptDefinitions.flatMap { it.asLegacyOrNull()?.annotationsForSamWithReceivers ?: emptyList() } + StorageComponentContainerContributor.registerExtension(environment.project, + CliSamWithReceiverComponentContributor(annotations) + ) + } + val project = environment.project + parser = KtPsiFactory(project) + } + + fun updateConfiguration(config: CompilerConfiguration) { + JvmTarget.fromString(config.jvm.target) + ?.let { environment.configuration.put(JVMConfigurationKeys.JVM_TARGET, it) } + } + + fun createContainer(sourcePath: Collection): Pair { + val trace = CliBindingTrace(environment.project) + val container = TopDownAnalyzerFacadeForJVM.createContainer( + project = environment.project, + files = sourcePath, + trace = trace, + configuration = environment.configuration, + packagePartProvider = environment::createPackagePartProvider, + // TODO FileBasedDeclarationProviderFactory keeps indices, re-use it across calls + declarationProviderFactory = ::FileBasedDeclarationProviderFactory + ) + return Pair(container, trace) + } + + override fun close() { + Disposer.dispose(disposable) + } +} diff --git a/server/src/main/kotlin/org/javacs/kt/compiler/CompilationType.kt b/server/src/main/kotlin/org/javacs/kt/compiler/CompilationType.kt new file mode 100644 index 000000000..087fd071c --- /dev/null +++ b/server/src/main/kotlin/org/javacs/kt/compiler/CompilationType.kt @@ -0,0 +1,12 @@ +package org.javacs.kt.compiler + +/** + * Determines the compilation environment used + * by the compiler (and thus the class path). + */ +enum class CompilationType { + /** Uses the default class path. */ + DEFAULT, + /** Uses the Kotlin DSL class path if available. */ + BUILD_SCRIPT +} diff --git a/server/src/main/kotlin/org/javacs/kt/compiler/Compiler.kt b/server/src/main/kotlin/org/javacs/kt/compiler/Compiler.kt index 585ee6d8a..a65d5d65a 100644 --- a/server/src/main/kotlin/org/javacs/kt/compiler/Compiler.kt +++ b/server/src/main/kotlin/org/javacs/kt/compiler/Compiler.kt @@ -1,66 +1,32 @@ -@file:OptIn(ExperimentalCompilerApi::class) -@file:Suppress("DEPRECATION") - package org.javacs.kt.compiler import com.intellij.lang.Language -import com.intellij.openapi.util.Disposer -import com.intellij.openapi.vfs.StandardFileSystems -import com.intellij.openapi.vfs.VirtualFileManager -import com.intellij.openapi.vfs.VirtualFileSystem import com.intellij.psi.PsiFile import com.intellij.psi.PsiFileFactory -import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.environment.setIdeaIoUseFallback -import org.jetbrains.kotlin.cli.jvm.config.addJavaSourceRoots -import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots -import org.jetbrains.kotlin.config.CommonConfigurationKeys -import org.jetbrains.kotlin.config.CompilerConfiguration as KotlinCompilerConfiguration import org.jetbrains.kotlin.container.ComponentProvider import org.jetbrains.kotlin.container.get -import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar import org.jetbrains.kotlin.idea.KotlinLanguage -import org.jetbrains.kotlin.metadata.jvm.deserialization.JvmProtoBufUtil import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.BindingTraceContext import org.jetbrains.kotlin.resolve.LazyTopDownAnalyzer import org.jetbrains.kotlin.resolve.TopDownAnalysisMode import org.jetbrains.kotlin.resolve.calls.components.InferenceSession import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo -import org.jetbrains.kotlin.resolve.lazy.declarations.FileBasedDeclarationProviderFactory -import org.jetbrains.kotlin.scripting.compiler.plugin.ScriptingCompilerConfigurationComponentRegistrar -import org.jetbrains.kotlin.scripting.compiler.plugin.definitions.CliScriptDefinitionProvider -import org.jetbrains.kotlin.scripting.configuration.ScriptingConfigurationKeys -import org.jetbrains.kotlin.scripting.definitions.ScriptDefinitionProvider -import org.jetbrains.kotlin.scripting.definitions.ScriptDefinition import org.jetbrains.kotlin.scripting.definitions.KotlinScriptDefinition // Legacy import org.jetbrains.kotlin.scripting.definitions.findScriptDefinition -import org.jetbrains.kotlin.scripting.definitions.getEnvironment -import org.jetbrains.kotlin.scripting.resolve.KotlinScriptDefinitionFromAnnotatedTemplate import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices import org.jetbrains.kotlin.util.KotlinFrontEndException import java.io.Closeable import java.nio.file.Path import java.nio.file.Paths -import java.net.URLClassLoader import java.util.concurrent.locks.ReentrantLock import kotlin.concurrent.withLock -import kotlin.script.dependencies.Environment -import kotlin.script.dependencies.ScriptContents -import kotlin.script.experimental.dependencies.ScriptDependencies -import kotlin.script.experimental.dependencies.DependenciesResolver -import kotlin.script.experimental.dependencies.DependenciesResolver.ResolveResult -import kotlin.script.experimental.host.ScriptingHostConfiguration -import kotlin.script.experimental.host.configurationDependencies -import kotlin.script.experimental.jvm.defaultJvmScriptingHostConfiguration -import kotlin.script.experimental.jvm.JvmDependency import org.javacs.kt.LOG import org.javacs.kt.CodegenConfiguration import org.javacs.kt.CompilerConfiguration import org.javacs.kt.ScriptsConfiguration -import org.javacs.kt.util.KotlinLSException import org.javacs.kt.util.LoggingMessageCollector import org.jetbrains.kotlin.cli.common.output.writeAllTo import org.jetbrains.kotlin.codegen.ClassBuilderFactories @@ -68,390 +34,9 @@ import org.jetbrains.kotlin.codegen.KotlinCodegenFacade import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.container.getService import org.jetbrains.kotlin.descriptors.ModuleDescriptor -import org.jetbrains.kotlin.cli.jvm.compiler.CliBindingTrace -import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles -import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment -import org.jetbrains.kotlin.cli.jvm.compiler.TopDownAnalyzerFacadeForJVM -import org.jetbrains.kotlin.cli.jvm.config.configureJdkClasspathRoots -import org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi -import org.jetbrains.kotlin.config.* import org.jetbrains.kotlin.resolve.scopes.LexicalScope -import org.jetbrains.kotlin.samWithReceiver.CliSamWithReceiverComponentContributor -import org.jetbrains.kotlin.extensions.StorageComponentContainerContributor import java.io.File -private val GRADLE_DSL_DEPENDENCY_PATTERN = Regex("^gradle-(?:kotlin-dsl|core).*\\.jar$") - -/** - * Kotlin compiler APIs used to parse, analyze and compile - * files and expressions. - */ -private class CompilationEnvironment( - javaSourcePath: Set, - classPath: Set, - scriptsConfig: ScriptsConfiguration -) : Closeable { - private val disposable = Disposer.newDisposable() - - val environment: KotlinCoreEnvironment - val parser: KtPsiFactory - val scripts: ScriptDefinitionProvider - - init { - environment = KotlinCoreEnvironment.createForProduction( - projectDisposable = disposable, - // Not to be confused with the CompilerConfiguration in the language server Configuration - configuration = KotlinCompilerConfiguration().apply { - val langFeatures = mutableMapOf() - for (langFeature in LanguageFeature.values()) { - langFeatures[langFeature] = LanguageFeature.State.ENABLED - } - val languageVersionSettings = LanguageVersionSettingsImpl( - LanguageVersion.LATEST_STABLE, - ApiVersion.createByLanguageVersion(LanguageVersion.LATEST_STABLE), - emptyMap(), - langFeatures - ) - - put(CommonConfigurationKeys.MODULE_NAME, JvmProtoBufUtil.DEFAULT_MODULE_NAME) - put(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS, languageVersionSettings) - put(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, LoggingMessageCollector) - add(ComponentRegistrar.PLUGIN_COMPONENT_REGISTRARS, ScriptingCompilerConfigurationComponentRegistrar()) - put(JVMConfigurationKeys.USE_PSI_CLASS_FILES_READING, true) - - // configure jvm runtime classpaths - configureJdkClasspathRoots() - - // Kotlin 1.8.20 requires us to specify the JDK home, otherwise java.* classes won't resolve - // See https://github.com/JetBrains/kotlin-compiler-server/pull/626 - val jdkHome = File(System.getProperty("java.home")) - put(JVMConfigurationKeys.JDK_HOME, jdkHome) - - addJvmClasspathRoots(classPath.map { it.toFile() }) - addJavaSourceRoots(javaSourcePath.map { it.toFile() }) - - if (scriptsConfig.enabled) { - // Setup script templates (e.g. used by Gradle's Kotlin DSL) - val scriptDefinitions: MutableList = mutableListOf(ScriptDefinition.getDefault(defaultJvmScriptingHostConfiguration)) - - val foundDSLDependency = classPath.any { GRADLE_DSL_DEPENDENCY_PATTERN.matches(it.fileName.toString()) } - if (scriptsConfig.buildScriptsEnabled && foundDSLDependency) { - LOG.info("Configuring Kotlin DSL script templates...") - - val scriptTemplates = listOf( - "org.gradle.kotlin.dsl.KotlinInitScript", - "org.gradle.kotlin.dsl.KotlinSettingsScript", - "org.gradle.kotlin.dsl.KotlinBuildScript" - ) - - try { - // Load template classes - val scriptClassLoader = URLClassLoader(classPath.map { it.toUri().toURL() }.toTypedArray()) - val fileClassPath = classPath.map { it.toFile() } - val scriptHostConfig = ScriptingHostConfiguration(defaultJvmScriptingHostConfiguration) { - configurationDependencies(JvmDependency(fileClassPath)) - } - // TODO: KotlinScriptDefinition will soon be deprecated, use - // ScriptDefinition.compilationConfiguration and its defaultImports instead - // of KotlinScriptDefinition.dependencyResolver - // TODO: Use ScriptDefinition.FromLegacyTemplate directly if possible - // scriptDefinitions = scriptTemplates.map { ScriptDefinition.FromLegacyTemplate(scriptHostConfig, scriptClassLoader.loadClass(it).kotlin) } - scriptDefinitions.addAll(scriptTemplates.map { ScriptDefinition.FromLegacy(scriptHostConfig, object : KotlinScriptDefinitionFromAnnotatedTemplate( - scriptClassLoader.loadClass(it).kotlin, - scriptHostConfig[ScriptingHostConfiguration.getEnvironment]?.invoke() - ) { - override fun isScript(fileName: String): Boolean { - // The pattern for KotlinSettingsScript doesn't seem to work well, so kinda "forcing it" for settings.gradle.kts files - if (this.template.simpleName == "KotlinSettingsScript" && fileName.endsWith("settings.gradle.kts")) { - return true - } - - return super.isScript(fileName) - } - - override val dependencyResolver: DependenciesResolver = object : DependenciesResolver { - override fun resolve(scriptContents: ScriptContents, environment: Environment) = ResolveResult.Success(ScriptDependencies( - imports = listOf( - "org.gradle.kotlin.dsl.*", - "org.gradle.kotlin.dsl.plugins.dsl.*", - "org.gradle.*", - "org.gradle.api.*", - "org.gradle.api.artifacts.*", - "org.gradle.api.artifacts.component.*", - "org.gradle.api.artifacts.dsl.*", - "org.gradle.api.artifacts.ivy.*", - "org.gradle.api.artifacts.maven.*", - "org.gradle.api.artifacts.query.*", - "org.gradle.api.artifacts.repositories.*", - "org.gradle.api.artifacts.result.*", - "org.gradle.api.artifacts.transform.*", - "org.gradle.api.artifacts.type.*", - "org.gradle.api.artifacts.verification.*", - "org.gradle.api.attributes.*", - "org.gradle.api.attributes.java.*", - "org.gradle.api.capabilities.*", - "org.gradle.api.component.*", - "org.gradle.api.credentials.*", - "org.gradle.api.distribution.*", - "org.gradle.api.distribution.plugins.*", - "org.gradle.api.execution.*", - "org.gradle.api.file.*", - "org.gradle.api.initialization.*", - "org.gradle.api.initialization.definition.*", - "org.gradle.api.initialization.dsl.*", - "org.gradle.api.invocation.*", - "org.gradle.api.java.archives.*", - "org.gradle.api.jvm.*", - "org.gradle.api.logging.*", - "org.gradle.api.logging.configuration.*", - "org.gradle.api.model.*", - "org.gradle.api.plugins.*", - "org.gradle.api.plugins.antlr.*", - "org.gradle.api.plugins.quality.*", - "org.gradle.api.plugins.scala.*", - "org.gradle.api.provider.*", - "org.gradle.api.publish.*", - "org.gradle.api.publish.ivy.*", - "org.gradle.api.publish.ivy.plugins.*", - "org.gradle.api.publish.ivy.tasks.*", - "org.gradle.api.publish.maven.*", - "org.gradle.api.publish.maven.plugins.*", - "org.gradle.api.publish.maven.tasks.*", - "org.gradle.api.publish.plugins.*", - "org.gradle.api.publish.tasks.*", - "org.gradle.api.reflect.*", - "org.gradle.api.reporting.*", - "org.gradle.api.reporting.components.*", - "org.gradle.api.reporting.dependencies.*", - "org.gradle.api.reporting.dependents.*", - "org.gradle.api.reporting.model.*", - "org.gradle.api.reporting.plugins.*", - "org.gradle.api.resources.*", - "org.gradle.api.services.*", - "org.gradle.api.specs.*", - "org.gradle.api.tasks.*", - "org.gradle.api.tasks.ant.*", - "org.gradle.api.tasks.application.*", - "org.gradle.api.tasks.bundling.*", - "org.gradle.api.tasks.compile.*", - "org.gradle.api.tasks.diagnostics.*", - "org.gradle.api.tasks.incremental.*", - "org.gradle.api.tasks.javadoc.*", - "org.gradle.api.tasks.options.*", - "org.gradle.api.tasks.scala.*", - "org.gradle.api.tasks.testing.*", - "org.gradle.api.tasks.testing.junit.*", - "org.gradle.api.tasks.testing.junitplatform.*", - "org.gradle.api.tasks.testing.testng.*", - "org.gradle.api.tasks.util.*", - "org.gradle.api.tasks.wrapper.*", - "org.gradle.authentication.*", - "org.gradle.authentication.aws.*", - "org.gradle.authentication.http.*", - "org.gradle.build.event.*", - "org.gradle.buildinit.plugins.*", - "org.gradle.buildinit.tasks.*", - "org.gradle.caching.*", - "org.gradle.caching.configuration.*", - "org.gradle.caching.http.*", - "org.gradle.caching.local.*", - "org.gradle.concurrent.*", - "org.gradle.external.javadoc.*", - "org.gradle.ide.visualstudio.*", - "org.gradle.ide.visualstudio.plugins.*", - "org.gradle.ide.visualstudio.tasks.*", - "org.gradle.ide.xcode.*", - "org.gradle.ide.xcode.plugins.*", - "org.gradle.ide.xcode.tasks.*", - "org.gradle.ivy.*", - "org.gradle.jvm.*", - "org.gradle.jvm.application.scripts.*", - "org.gradle.jvm.application.tasks.*", - "org.gradle.jvm.platform.*", - "org.gradle.jvm.plugins.*", - "org.gradle.jvm.tasks.*", - "org.gradle.jvm.tasks.api.*", - "org.gradle.jvm.test.*", - "org.gradle.jvm.toolchain.*", - "org.gradle.language.*", - "org.gradle.language.assembler.*", - "org.gradle.language.assembler.plugins.*", - "org.gradle.language.assembler.tasks.*", - "org.gradle.language.base.*", - "org.gradle.language.base.artifact.*", - "org.gradle.language.base.compile.*", - "org.gradle.language.base.plugins.*", - "org.gradle.language.base.sources.*", - "org.gradle.language.c.*", - "org.gradle.language.c.plugins.*", - "org.gradle.language.c.tasks.*", - "org.gradle.language.coffeescript.*", - "org.gradle.language.cpp.*", - "org.gradle.language.cpp.plugins.*", - "org.gradle.language.cpp.tasks.*", - "org.gradle.language.java.*", - "org.gradle.language.java.artifact.*", - "org.gradle.language.java.plugins.*", - "org.gradle.language.java.tasks.*", - "org.gradle.language.javascript.*", - "org.gradle.language.jvm.*", - "org.gradle.language.jvm.plugins.*", - "org.gradle.language.jvm.tasks.*", - "org.gradle.language.nativeplatform.*", - "org.gradle.language.nativeplatform.tasks.*", - "org.gradle.language.objectivec.*", - "org.gradle.language.objectivec.plugins.*", - "org.gradle.language.objectivec.tasks.*", - "org.gradle.language.objectivecpp.*", - "org.gradle.language.objectivecpp.plugins.*", - "org.gradle.language.objectivecpp.tasks.*", - "org.gradle.language.plugins.*", - "org.gradle.language.rc.*", - "org.gradle.language.rc.plugins.*", - "org.gradle.language.rc.tasks.*", - "org.gradle.language.routes.*", - "org.gradle.language.scala.*", - "org.gradle.language.scala.plugins.*", - "org.gradle.language.scala.tasks.*", - "org.gradle.language.scala.toolchain.*", - "org.gradle.language.swift.*", - "org.gradle.language.swift.plugins.*", - "org.gradle.language.swift.tasks.*", - "org.gradle.language.twirl.*", - "org.gradle.maven.*", - "org.gradle.model.*", - "org.gradle.nativeplatform.*", - "org.gradle.nativeplatform.platform.*", - "org.gradle.nativeplatform.plugins.*", - "org.gradle.nativeplatform.tasks.*", - "org.gradle.nativeplatform.test.*", - "org.gradle.nativeplatform.test.cpp.*", - "org.gradle.nativeplatform.test.cpp.plugins.*", - "org.gradle.nativeplatform.test.cunit.*", - "org.gradle.nativeplatform.test.cunit.plugins.*", - "org.gradle.nativeplatform.test.cunit.tasks.*", - "org.gradle.nativeplatform.test.googletest.*", - "org.gradle.nativeplatform.test.googletest.plugins.*", - "org.gradle.nativeplatform.test.plugins.*", - "org.gradle.nativeplatform.test.tasks.*", - "org.gradle.nativeplatform.test.xctest.*", - "org.gradle.nativeplatform.test.xctest.plugins.*", - "org.gradle.nativeplatform.test.xctest.tasks.*", - "org.gradle.nativeplatform.toolchain.*", - "org.gradle.nativeplatform.toolchain.plugins.*", - "org.gradle.normalization.*", - "org.gradle.platform.base.*", - "org.gradle.platform.base.binary.*", - "org.gradle.platform.base.component.*", - "org.gradle.platform.base.plugins.*", - "org.gradle.play.*", - "org.gradle.play.distribution.*", - "org.gradle.play.platform.*", - "org.gradle.play.plugins.*", - "org.gradle.play.plugins.ide.*", - "org.gradle.play.tasks.*", - "org.gradle.play.toolchain.*", - "org.gradle.plugin.devel.*", - "org.gradle.plugin.devel.plugins.*", - "org.gradle.plugin.devel.tasks.*", - "org.gradle.plugin.management.*", - "org.gradle.plugin.use.*", - "org.gradle.plugins.ear.*", - "org.gradle.plugins.ear.descriptor.*", - "org.gradle.plugins.ide.*", - "org.gradle.plugins.ide.api.*", - "org.gradle.plugins.ide.eclipse.*", - "org.gradle.plugins.ide.idea.*", - "org.gradle.plugins.javascript.base.*", - "org.gradle.plugins.javascript.coffeescript.*", - "org.gradle.plugins.javascript.envjs.*", - "org.gradle.plugins.javascript.envjs.browser.*", - "org.gradle.plugins.javascript.envjs.http.*", - "org.gradle.plugins.javascript.envjs.http.simple.*", - "org.gradle.plugins.javascript.jshint.*", - "org.gradle.plugins.javascript.rhino.*", - "org.gradle.plugins.signing.*", - "org.gradle.plugins.signing.signatory.*", - "org.gradle.plugins.signing.signatory.pgp.*", - "org.gradle.plugins.signing.type.*", - "org.gradle.plugins.signing.type.pgp.*", - "org.gradle.process.*", - "org.gradle.swiftpm.*", - "org.gradle.swiftpm.plugins.*", - "org.gradle.swiftpm.tasks.*", - "org.gradle.testing.base.*", - "org.gradle.testing.base.plugins.*", - "org.gradle.testing.jacoco.plugins.*", - "org.gradle.testing.jacoco.tasks.*", - "org.gradle.testing.jacoco.tasks.rules.*", - "org.gradle.testkit.runner.*", - "org.gradle.vcs.*", - "org.gradle.vcs.git.*", - "org.gradle.work.*", - "org.gradle.workers.*" - ) - )) - } - }) }) - } catch (e: Exception) { - LOG.error("Error while loading script template classes") - LOG.printStackTrace(e) - } - } - - LOG.info("Adding script definitions ${scriptDefinitions.map { it.asLegacyOrNull()?.template?.simpleName }}") - addAll(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS, scriptDefinitions) - } - }, - configFiles = EnvironmentConfigFiles.JVM_CONFIG_FILES - ) - - // hacky way to support SamWithReceiverAnnotations for scripts - val scriptDefinitions: List = environment.configuration.getList(ScriptingConfigurationKeys.SCRIPT_DEFINITIONS) - scriptDefinitions.takeIf { it.isNotEmpty() }?.let { - val annotations = scriptDefinitions.flatMap { it.asLegacyOrNull()?.annotationsForSamWithReceivers ?: emptyList() } - StorageComponentContainerContributor.registerExtension(environment.project, CliSamWithReceiverComponentContributor(annotations)) - } - val project = environment.project - parser = KtPsiFactory(project) - scripts = ScriptDefinitionProvider.getInstance(project)!! as CliScriptDefinitionProvider - } - - fun updateConfiguration(config: CompilerConfiguration) { - JvmTarget.fromString(config.jvm.target) - ?.let { environment.configuration.put(JVMConfigurationKeys.JVM_TARGET, it) } - } - - fun createContainer(sourcePath: Collection): Pair { - val trace = CliBindingTrace(environment.project) - val container = TopDownAnalyzerFacadeForJVM.createContainer( - project = environment.project, - files = sourcePath, - trace = trace, - configuration = environment.configuration, - packagePartProvider = environment::createPackagePartProvider, - // TODO FileBasedDeclarationProviderFactory keeps indices, re-use it across calls - declarationProviderFactory = ::FileBasedDeclarationProviderFactory - ) - return Pair(container, trace) - } - - override fun close() { - Disposer.dispose(disposable) - } -} - -/** - * Determines the compilation environment used - * by the compiler (and thus the class path). - */ -enum class CompilationKind { - /** Uses the default class path. */ - DEFAULT, - /** Uses the Kotlin DSL class path if available. */ - BUILD_SCRIPT -} - /** * Incrementally compiles files and expressions. * The basic strategy for compiling one file at-a-time is outlined in OneFilePerformance. @@ -465,7 +50,6 @@ class Compiler( private val outputDirectory: File, ) : Closeable { private var closed = false - private val localFileSystem: VirtualFileSystem private val defaultCompileEnvironment = CompilationEnvironment(javaSourcePath, classPath, scriptsConfig) private val buildScriptCompileEnvironment = buildScriptClassPath @@ -479,10 +63,6 @@ class Compiler( } } - init { - localFileSystem = VirtualFileManager.getInstance().getFileSystem(StandardFileSystems.FILE_PROTOCOL) - } - /** * Updates the compiler environment using the given * configuration (which is a class from this project). @@ -492,7 +72,7 @@ class Compiler( buildScriptCompileEnvironment?.updateConfiguration(config) } - fun createPsiFile(content: String, file: Path = Paths.get("dummy.virtual.kt"), language: Language = KotlinLanguage.INSTANCE, kind: CompilationKind = CompilationKind.DEFAULT): PsiFile { + private fun createPsiFile(content: String, file: Path = Paths.get("dummy.virtual.kt"), language: Language = KotlinLanguage.INSTANCE, kind: CompilationType = CompilationType.DEFAULT): PsiFile { assert(!content.contains('\r')) val new = psiFileFactoryFor(kind).createFileFromText(file.toString(), language, content, true, false) @@ -501,15 +81,10 @@ class Compiler( return new } - fun createKtFile(content: String, file: Path = Paths.get("dummy.virtual.kt"), kind: CompilationKind = CompilationKind.DEFAULT): KtFile = - createPsiFile(content, file, language = KotlinLanguage.INSTANCE, kind = kind) as KtFile - - fun createKtExpression(content: String, file: Path = Paths.get("dummy.virtual.kt"), kind: CompilationKind = CompilationKind.DEFAULT): KtExpression { - val property = createKtDeclaration("val x = $content", file, kind) as KtProperty - return property.initializer!! - } + fun createKtFile(content: String, file: Path = Paths.get("dummy.virtual.kt"), kind: CompilationType = CompilationType.DEFAULT): KtFile = + createPsiFile(content, file, kind = kind) as KtFile - fun createKtDeclaration(content: String, file: Path = Paths.get("dummy.virtual.kt"), kind: CompilationKind = CompilationKind.DEFAULT): KtDeclaration { + fun createKtDeclaration(content: String, file: Path = Paths.get("dummy.virtual.kt"), kind: CompilationType = CompilationType.DEFAULT): KtDeclaration { val parse = createKtFile(content, file, kind) val declarations = parse.declarations @@ -527,19 +102,19 @@ class Compiler( else return onlyDeclaration } - private fun compileEnvironmentFor(kind: CompilationKind): CompilationEnvironment = when (kind) { - CompilationKind.DEFAULT -> defaultCompileEnvironment - CompilationKind.BUILD_SCRIPT -> buildScriptCompileEnvironment ?: defaultCompileEnvironment + private fun compileEnvironmentFor(kind: CompilationType): CompilationEnvironment = when (kind) { + CompilationType.DEFAULT -> defaultCompileEnvironment + CompilationType.BUILD_SCRIPT -> buildScriptCompileEnvironment ?: defaultCompileEnvironment } - fun psiFileFactoryFor(kind: CompilationKind): PsiFileFactory = + fun psiFileFactoryFor(kind: CompilationType): PsiFileFactory = PsiFileFactory.getInstance(compileEnvironmentFor(kind).environment.project) - fun compileKtFile(file: KtFile, sourcePath: Collection, kind: CompilationKind = CompilationKind.DEFAULT): Pair = + fun compileKtFile(file: KtFile, sourcePath: Collection, kind: CompilationType = CompilationType.DEFAULT): Pair = compileKtFiles(listOf(file), sourcePath, kind) - fun compileKtFiles(files: Collection, sourcePath: Collection, kind: CompilationKind = CompilationKind.DEFAULT): Pair { - if (kind == CompilationKind.BUILD_SCRIPT) { + fun compileKtFiles(files: Collection, sourcePath: Collection, kind: CompilationType = CompilationType.DEFAULT): Pair { + if (kind == CompilationType.BUILD_SCRIPT) { // Print the (legacy) script template used by the compiled Kotlin DSL build file files.forEach { LOG.debug { "$it -> ScriptDefinition: ${it.findScriptDefinition()?.asLegacyOrNull()?.template?.simpleName}" } } } @@ -553,8 +128,13 @@ class Compiler( } } - fun compileKtExpression(expression: KtExpression, scopeWithImports: LexicalScope, sourcePath: Collection, kind: CompilationKind = CompilationKind.DEFAULT): Pair? = - try { + fun compileKtExpression( + expression: KtExpression, + scopeWithImports: LexicalScope, + sourcePath: Collection, + kind: CompilationType = CompilationType.DEFAULT + ): Pair? { + return try { // Use same lock as 'compileFile' to avoid concurrency issues such as #42 compileLock.withLock { val compileEnv = compileEnvironmentFor(kind) @@ -579,13 +159,17 @@ class Compiler( """.trimIndent()) null } + } fun removeGeneratedCode(files: Collection) { files.forEach { file -> file.declarations.forEach { declaration -> - outputDirectory.resolve( + val deleted = outputDirectory.resolve( file.packageFqName.asString().replace(".", File.separator) + File.separator + declaration.name + ".class" ).delete() + if (!deleted) { + LOG.warn("Failed to delete generated class file for $declaration") + } } } } @@ -593,7 +177,7 @@ class Compiler( fun generateCode(module: ModuleDescriptor, bindingContext: BindingContext, files: Collection) { outputDirectory.takeIf { codegenConfig.enabled }?.let { compileLock.withLock { - val compileEnv = compileEnvironmentFor(CompilationKind.DEFAULT) + val compileEnv = compileEnvironmentFor(CompilationType.DEFAULT) val state = GenerationState.Builder( project = compileEnv.environment.project, builderFactory = ClassBuilderFactories.BINARIES, diff --git a/server/src/main/kotlin/org/javacs/kt/completion/Completions.kt b/server/src/main/kotlin/org/javacs/kt/completion/Completions.kt index 509f1e6b8..ef66d2a98 100644 --- a/server/src/main/kotlin/org/javacs/kt/completion/Completions.kt +++ b/server/src/main/kotlin/org/javacs/kt/completion/Completions.kt @@ -5,9 +5,6 @@ import org.eclipse.lsp4j.CompletionItem import org.eclipse.lsp4j.CompletionItemKind import org.eclipse.lsp4j.CompletionItemTag import org.eclipse.lsp4j.CompletionList -import org.eclipse.lsp4j.TextEdit -import org.eclipse.lsp4j.Range -import org.eclipse.lsp4j.Position import org.javacs.kt.CompiledFile import org.javacs.kt.LOG import org.javacs.kt.CompletionConfiguration @@ -19,7 +16,6 @@ import org.javacs.kt.util.noResult import org.javacs.kt.util.stringDistance import org.javacs.kt.util.toPath import org.javacs.kt.util.onEachIndexed -import org.javacs.kt.position.location import org.javacs.kt.imports.getImportTextEditEntry import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.* @@ -628,9 +624,3 @@ private fun doesntLookLikePackage(packageDirective: KtPackageDirective): Sequenc return emptySequence() } - -private fun empty(message: String): CompletionList { - LOG.debug(message) - - return CompletionList(true, emptyList()) -} diff --git a/server/src/main/kotlin/org/javacs/kt/definition/DefinitionHandler.kt b/server/src/main/kotlin/org/javacs/kt/definition/DefinitionHandler.kt new file mode 100644 index 000000000..2783f0458 --- /dev/null +++ b/server/src/main/kotlin/org/javacs/kt/definition/DefinitionHandler.kt @@ -0,0 +1,124 @@ +package org.javacs.kt.definition + +import java.io.File +import java.nio.file.Path +import java.nio.file.Paths +import org.eclipse.lsp4j.Location +import org.eclipse.lsp4j.Range +import org.javacs.kt.CompiledFile +import org.javacs.kt.CompilerClassPath +import org.javacs.kt.ExternalSourcesConfiguration +import org.javacs.kt.LOG +import org.javacs.kt.externalsources.ClassContentProvider +import org.javacs.kt.externalsources.KlsURI +import org.javacs.kt.externalsources.toKlsURI +import org.javacs.kt.position.isZero +import org.javacs.kt.position.location +import org.javacs.kt.position.position +import org.javacs.kt.util.TemporaryDirectory +import org.javacs.kt.util.parseURI +import org.javacs.kt.util.partitionAroundLast +import org.jetbrains.kotlin.descriptors.ConstructorDescriptor +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi +import org.jetbrains.kotlin.psi.KtNamedDeclaration + +/** Handles "go to definition" functionality for Kotlin code */ +class DefinitionHandler( + private val classContentProvider: ClassContentProvider, + private val tempDir: TemporaryDirectory, + private val config: ExternalSourcesConfiguration, + private val compilerClassPath: CompilerClassPath, +) { + private val cachedTempFiles = mutableMapOf() + private val definitionPattern = Regex("(?:class|interface|object|fun)\\s+(\\w+)") + + /** Finds the definition location for a symbol at the given cursor position */ + fun goToDefinition(file: CompiledFile, cursor: Int): Location? { + val (_, target) = file.referenceExpressionAtPoint(cursor) ?: return null + LOG.info("Found declaration descriptor {}", target) + + val destination = getInitialLocation(target) ?: return null + + if (isInsideArchive(destination.uri)) { + handleArchiveSource(target, destination) + } + + return destination + } + + private fun getInitialLocation(target: DeclarationDescriptor): Location? { + var destination = location(target) + + val psi = target.findPsi() + if (psi is KtNamedDeclaration) { + destination = psi.nameIdentifier?.let(::location) ?: destination + } + + return destination + } + + private fun handleArchiveSource(target: DeclarationDescriptor, destination: Location) { + parseURI(destination.uri).toKlsURI()?.let { klsURI -> + val (klsSourceURI, content) = classContentProvider.contentOf(klsURI) + + destination.uri = + if (config.useKlsScheme) { + klsSourceURI.toString() + } else { + getOrCreateTempFile(klsSourceURI, content).toUri().toString() + } + + if (destination.range.isZero) { + updateRangeFromContent(target, content, destination) + } + } + } + + private fun getOrCreateTempFile(klsSourceURI: KlsURI, content: String): Path { + return cachedTempFiles[klsSourceURI] + ?: run { + val (name, extension) = getFileNameParts(klsSourceURI) + tempDir.createTempFile(name, extension).also { + it.toFile().writeText(content) + cachedTempFiles[klsSourceURI] = it + } + } + } + + private fun getFileNameParts(klsSourceURI: KlsURI): Pair { + val name = klsSourceURI.fileName.partitionAroundLast(".").first + val extensionWithoutDot = klsSourceURI.fileExtension + val extension = if (extensionWithoutDot != null) ".$extensionWithoutDot" else "" + return Pair(name, extension) + } + + private fun updateRangeFromContent( + target: DeclarationDescriptor, + content: String, + destination: Location, + ) { + val name = + when (target) { + is ConstructorDescriptor -> target.constructedClass.name.toString() + else -> target.name.toString() + } + + definitionPattern + .findAll(content) + .map { it.groups[1]!! } + .find { it.value == name } + ?.range + ?.let { range -> + destination.range = + Range(position(content, range.first), position(content, range.last)) + } + } + + private fun isInsideArchive(uri: String): Boolean = + uri.contains(".jar!") || + uri.contains(".zip!") || + compilerClassPath.javaHome?.let { + Paths.get(parseURI(uri)).toString().startsWith(File(it).path) + } ?: false +} diff --git a/server/src/main/kotlin/org/javacs/kt/definition/GoToDefinition.kt b/server/src/main/kotlin/org/javacs/kt/definition/GoToDefinition.kt deleted file mode 100644 index 77c8a05de..000000000 --- a/server/src/main/kotlin/org/javacs/kt/definition/GoToDefinition.kt +++ /dev/null @@ -1,96 +0,0 @@ -package org.javacs.kt.definition - -import org.eclipse.lsp4j.Location -import org.eclipse.lsp4j.Range -import java.nio.file.Path -import org.javacs.kt.CompiledFile -import org.javacs.kt.CompilerClassPath -import org.javacs.kt.LOG -import org.javacs.kt.ExternalSourcesConfiguration -import org.javacs.kt.externalsources.ClassContentProvider -import org.javacs.kt.externalsources.toKlsURI -import org.javacs.kt.externalsources.KlsURI -import org.javacs.kt.position.location -import org.javacs.kt.position.isZero -import org.javacs.kt.position.position -import org.javacs.kt.util.partitionAroundLast -import org.javacs.kt.util.TemporaryDirectory -import org.javacs.kt.util.parseURI -import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi -import org.jetbrains.kotlin.psi.KtNamedDeclaration -import org.jetbrains.kotlin.descriptors.ConstructorDescriptor -import java.io.File -import java.nio.file.Paths - -private val cachedTempFiles = mutableMapOf() -private val definitionPattern = Regex("(?:class|interface|object|fun)\\s+(\\w+)") - -fun goToDefinition( - file: CompiledFile, - cursor: Int, - classContentProvider: ClassContentProvider, - tempDir: TemporaryDirectory, - config: ExternalSourcesConfiguration, - cp: CompilerClassPath -): Location? { - val (_, target) = file.referenceExpressionAtPoint(cursor) ?: return null - - LOG.info("Found declaration descriptor {}", target) - var destination = location(target) - val psi = target.findPsi() - - if (psi is KtNamedDeclaration) { - destination = psi.nameIdentifier?.let(::location) ?: destination - } - - if (destination != null) { - val rawClassURI = destination.uri - - if (isInsideArchive(rawClassURI, cp)) { - parseURI(rawClassURI).toKlsURI()?.let { klsURI -> - val (klsSourceURI, content) = classContentProvider.contentOf(klsURI) - - if (config.useKlsScheme) { - // Defer decompilation until a jarClassContents request is sent - destination.uri = klsSourceURI.toString() - } else { - // Return the path to a temporary file - // since the client has not opted into - // or does not support KLS URIs - val tmpFile = cachedTempFiles[klsSourceURI] ?: run { - val name = klsSourceURI.fileName.partitionAroundLast(".").first - val extensionWithoutDot = klsSourceURI.fileExtension - val extension = if (extensionWithoutDot != null) ".$extensionWithoutDot" else "" - tempDir.createTempFile(name, extension) - .also { - it.toFile().writeText(content) - cachedTempFiles[klsSourceURI] = it - } - } - - destination.uri = tmpFile.toUri().toString() - } - - if (destination.range.isZero) { - // Try to find the definition inside the source directly - val name = when (target) { - is ConstructorDescriptor -> target.constructedClass.name.toString() - else -> target.name.toString() - } - definitionPattern.findAll(content) - .map { it.groups[1]!! } - .find { it.value == name } - ?.let { it.range } - ?.let { destination.range = Range(position(content, it.first), position(content, it.last)) } - } - } - } - } - - return destination -} - -private fun isInsideArchive(uri: String, cp: CompilerClassPath) = - uri.contains(".jar!") || uri.contains(".zip!") || cp.javaHome?.let { - Paths.get(parseURI(uri)).toString().startsWith(File(it).path) - } ?: false diff --git a/server/src/main/kotlin/org/javacs/kt/docs/FindDoc.kt b/server/src/main/kotlin/org/javacs/kt/docs/FindDoc.kt index d7e3e88de..baaa6fc2b 100644 --- a/server/src/main/kotlin/org/javacs/kt/docs/FindDoc.kt +++ b/server/src/main/kotlin/org/javacs/kt/docs/FindDoc.kt @@ -11,9 +11,7 @@ import org.jetbrains.kotlin.psi.psiUtil.parents import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils fun findDoc(declaration: DeclarationDescriptorWithSource): KDocTag? { - val source = DescriptorToSourceUtils.descriptorToDeclaration(declaration)?.navigationElement - - return when (source) { + return when (val source = DescriptorToSourceUtils.descriptorToDeclaration(declaration)?.navigationElement) { is KtParameter -> { var container = source.parents.filterIsInstance().firstOrNull() ?: return null if (container is KtPrimaryConstructor) @@ -37,4 +35,4 @@ fun findDoc(declaration: DeclarationDescriptorWithSource): KDocTag? { } else -> null } -} \ No newline at end of file +} diff --git a/server/src/main/kotlin/org/javacs/kt/externalsources/KlsURI.kt b/server/src/main/kotlin/org/javacs/kt/externalsources/KlsURI.kt index 9368fc6e7..6fec76326 100644 --- a/server/src/main/kotlin/org/javacs/kt/externalsources/KlsURI.kt +++ b/server/src/main/kotlin/org/javacs/kt/externalsources/KlsURI.kt @@ -99,7 +99,10 @@ data class KlsURI(val fileUri: URI, val query: Map) { private fun toURI(): URI = URI(fileUri.toString() + queryString) - private fun toJarURL(): URL = URL("jar:${fileUri.schemeSpecificPart}") + private fun toJarURL(): URL { + val jarUri = URI("jar", fileUri.schemeSpecificPart, null) + return jarUri.toURL() + } private fun openJarURLConnection() = toJarURL().openConnection() as JarURLConnection diff --git a/server/src/main/kotlin/org/javacs/kt/formatting/FormattingService.kt b/server/src/main/kotlin/org/javacs/kt/formatting/FormattingService.kt index 97cc16bc9..2e243107e 100644 --- a/server/src/main/kotlin/org/javacs/kt/formatting/FormattingService.kt +++ b/server/src/main/kotlin/org/javacs/kt/formatting/FormattingService.kt @@ -1,8 +1,7 @@ package org.javacs.kt.formatting -import org.javacs.kt.Configuration import org.javacs.kt.FormattingConfiguration -import org.eclipse.lsp4j.FormattingOptions as LspFromattingOptions +import org.eclipse.lsp4j.FormattingOptions as LspFormattingOptions private const val DEFAULT_INDENT = 4 @@ -16,6 +15,6 @@ class FormattingService(private val config: FormattingConfiguration) { fun formatKotlinCode( code: String, - options: LspFromattingOptions = LspFromattingOptions(DEFAULT_INDENT, true) + options: LspFormattingOptions = LspFormattingOptions(DEFAULT_INDENT, true) ): String = this.formatter.format(code, options) } diff --git a/server/src/main/kotlin/org/javacs/kt/j2k/JavaToKotlinConverter.kt b/server/src/main/kotlin/org/javacs/kt/j2k/JavaToKotlinConverter.kt index 41b446883..543105772 100644 --- a/server/src/main/kotlin/org/javacs/kt/j2k/JavaToKotlinConverter.kt +++ b/server/src/main/kotlin/org/javacs/kt/j2k/JavaToKotlinConverter.kt @@ -1,16 +1,12 @@ package org.javacs.kt.j2k import com.intellij.lang.java.JavaLanguage -import com.intellij.psi.PsiFileFactory -import com.intellij.openapi.project.Project -// import org.jetbrains.kotlin.j2k.JavaToKotlinTranslator import org.javacs.kt.LOG import org.javacs.kt.compiler.Compiler -import org.javacs.kt.compiler.CompilationKind -import org.javacs.kt.util.nonNull +import org.javacs.kt.compiler.CompilationType fun convertJavaToKotlin(javaCode: String, compiler: Compiler): String { - val psiFactory = compiler.psiFileFactoryFor(CompilationKind.DEFAULT) + val psiFactory = compiler.psiFileFactoryFor(CompilationType.DEFAULT) val javaAST = psiFactory.createFileFromText("snippet.java", JavaLanguage.INSTANCE, javaCode) LOG.info("Parsed {} to {}", javaCode, javaAST) diff --git a/server/src/main/kotlin/org/javacs/kt/j2k/JavaTypeConverter.kt b/server/src/main/kotlin/org/javacs/kt/j2k/JavaTypeConverter.kt index 842da2fd1..917e9d4d5 100644 --- a/server/src/main/kotlin/org/javacs/kt/j2k/JavaTypeConverter.kt +++ b/server/src/main/kotlin/org/javacs/kt/j2k/JavaTypeConverter.kt @@ -43,9 +43,9 @@ object JavaTypeConverter : PsiTypeVisitor() { } override fun visitWildcardType(wildcardType: PsiWildcardType): String = - if (wildcardType.isSuper()) { + if (wildcardType.isSuper) { "in ${wildcardType.bound?.accept(this)}" - } else if (wildcardType.isExtends()) { + } else if (wildcardType.isExtends) { "out ${wildcardType.bound?.accept(this)}" } else { super.visitWildcardType(wildcardType) ?: "?" diff --git a/server/src/main/kotlin/org/javacs/kt/position/Position.kt b/server/src/main/kotlin/org/javacs/kt/position/Position.kt index 3efba5ded..f0448729b 100644 --- a/server/src/main/kotlin/org/javacs/kt/position/Position.kt +++ b/server/src/main/kotlin/org/javacs/kt/position/Position.kt @@ -92,8 +92,7 @@ fun location(declaration: DeclarationDescriptor): Location? { if (psiLocation != null) return psiLocation if (declaration is DeclarationDescriptorWithSource) { - val sourceFile = declaration.source.containingFile - when (sourceFile) { + when (val sourceFile = declaration.source.containingFile) { is PsiSourceFile -> { val file = sourceFile.psiFile.toURIString() return Location(file, Range(Position(0, 0), Position(0, 0))) diff --git a/server/src/main/kotlin/org/javacs/kt/progress/Progress.kt b/server/src/main/kotlin/org/javacs/kt/progress/Progress.kt index b7c64ee15..0e97d9523 100644 --- a/server/src/main/kotlin/org/javacs/kt/progress/Progress.kt +++ b/server/src/main/kotlin/org/javacs/kt/progress/Progress.kt @@ -5,28 +5,28 @@ import java.util.concurrent.CompletableFuture /** A facility for emitting progress notifications. */ interface Progress : Closeable { - /** - * Updates the progress percentage. The - * value should be in the range [0, 100]. - */ + /** Updates the progress percentage. The value should be in the range [0, 100]. */ fun update(message: String? = null, percent: Int? = null) object None : Progress { - override fun update(message: String?, percent: Int?) {} + override fun update(message: String?, percent: Int?) { + // Do nothing + } - override fun close() {} + override fun close() { + // Do nothing + } } - interface Factory { - /** - * Creates a new progress listener with - * the given label. The label is intended - * to be human-readable. - */ + /** + * Creates a new progress listener with the given label. The label is intended to be + * human-readable. + */ + fun interface Factory { fun create(label: String): CompletableFuture - object None : Factory { - override fun create(label: String): CompletableFuture = CompletableFuture.completedFuture(Progress.None) + companion object { + val None: Factory = Factory { CompletableFuture.completedFuture(Progress.None) } } } } diff --git a/server/src/test/kotlin/org/javacs/kt/DebouncerTest.kt b/server/src/test/kotlin/org/javacs/kt/DebouncerTest.kt index 210c92b30..3056b422f 100644 --- a/server/src/test/kotlin/org/javacs/kt/DebouncerTest.kt +++ b/server/src/test/kotlin/org/javacs/kt/DebouncerTest.kt @@ -7,17 +7,17 @@ import org.javacs.kt.util.Debouncer import java.time.Duration class DebouncerTest { - val debounce = Debouncer(Duration.ofSeconds(1)) + val debouncer = Debouncer(Duration.ofSeconds(1)) var counter = 0 @Test fun callQuickly() { for (i in 1..10) { - debounce.schedule { + debouncer.schedule { counter++ } } - debounce.waitForPendingTask() + debouncer.waitForPendingTask() assertThat(counter, equalTo(1)) } diff --git a/server/src/test/kotlin/org/javacs/kt/DiagnosticTest.kt b/server/src/test/kotlin/org/javacs/kt/DiagnosticTest.kt index 023feb69d..3a9ce67c5 100644 --- a/server/src/test/kotlin/org/javacs/kt/DiagnosticTest.kt +++ b/server/src/test/kotlin/org/javacs/kt/DiagnosticTest.kt @@ -11,7 +11,7 @@ import org.junit.Test class DiagnosticTest : SingleFileTestFixture("diagnostic", "Diagnostics.kt") { @Test fun `report diagnostics on open`() { - languageServer.textDocumentService.debounceLint.waitForPendingTask() + languageServer.textDocumentService.lintDebouncer.waitForPendingTask() assertThat(diagnostics, hasSize(2)) assertThat(errors, hasSize(1)) @@ -23,7 +23,7 @@ class DiagnosticTest : SingleFileTestFixture("diagnostic", "Diagnostics.kt") { // Trigger a diagnostics update via a dummy change. replace(file, 6, 1, "", " ") - languageServer.textDocumentService.debounceLint.waitForPendingTask() + languageServer.textDocumentService.lintDebouncer.waitForPendingTask() assertThat(diagnostics, hasSize(1)) assertThat(errors, hasSize(1)) @@ -35,7 +35,7 @@ class DiagnosticTest : SingleFileTestFixture("diagnostic", "Diagnostics.kt") { // Trigger a diagnostics update via a dummy change. replace(file, 1, 1, "", " ") - languageServer.textDocumentService.debounceLint.waitForPendingTask() + languageServer.textDocumentService.lintDebouncer.waitForPendingTask() assertThat(diagnostics, empty()) } @@ -49,7 +49,7 @@ class DiagnosticTest : SingleFileTestFixture("diagnostic", "Diagnostics.kt") { text = newText } - languageServer.textDocumentService.debounceLint.waitForPendingTask() + languageServer.textDocumentService.lintDebouncer.waitForPendingTask() assertThat(diagnostics, not(empty())) assertThat(languageServer.textDocumentService.lintCount, lessThan(5)) @@ -57,7 +57,7 @@ class DiagnosticTest : SingleFileTestFixture("diagnostic", "Diagnostics.kt") { @Test fun `linting should not be dropped if another linting is running`() { var callbackCount = 0 - languageServer.textDocumentService.debounceLint.waitForPendingTask() + languageServer.textDocumentService.lintDebouncer.waitForPendingTask() languageServer.textDocumentService.lintRecompilationCallback = { if (callbackCount++ == 0) { replace(file, 7, 9, "return 11", "") @@ -69,11 +69,11 @@ class DiagnosticTest : SingleFileTestFixture("diagnostic", "Diagnostics.kt") { while (callbackCount < 2) { try { - languageServer.textDocumentService.debounceLint.waitForPendingTask() + languageServer.textDocumentService.lintDebouncer.waitForPendingTask() } catch (ex: CancellationException) {} } - languageServer.textDocumentService.debounceLint.waitForPendingTask() + languageServer.textDocumentService.lintDebouncer.waitForPendingTask() assertThat(diagnostics, empty()) languageServer.textDocumentService.lintRecompilationCallback = {} } diff --git a/server/src/test/kotlin/org/javacs/kt/LanguageServerTestFixture.kt b/server/src/test/kotlin/org/javacs/kt/LanguageServerTestFixture.kt index 403447d59..83e412fba 100644 --- a/server/src/test/kotlin/org/javacs/kt/LanguageServerTestFixture.kt +++ b/server/src/test/kotlin/org/javacs/kt/LanguageServerTestFixture.kt @@ -4,6 +4,7 @@ import org.eclipse.lsp4j.* import org.eclipse.lsp4j.services.LanguageClient import org.junit.Before import org.junit.After +import java.net.URI import java.nio.file.Path import java.nio.file.Paths import java.util.concurrent.CompletableFuture @@ -26,8 +27,8 @@ abstract class LanguageServerTestFixture( return testResources.resolve(relativeWorkspaceRoot) } - private fun createLanguageServer(config: Configuration): KotlinLanguageServer { - val languageServer = KotlinLanguageServer(config) + private fun createLanguageServer(config: Configuration): Server { + val languageServer = Server(config) val init = InitializeParams().apply { capabilities = ClientCapabilities().apply { textDocument = TextDocumentClientCapabilities().apply { @@ -79,7 +80,7 @@ abstract class LanguageServerTestFixture( return CompletionParams(fileId, position) } - fun textDocumentPosition(relativePath: String, line: Int, column: Int): TextDocumentPositionParams = + private fun textDocumentPosition(relativePath: String, line: Int, column: Int): TextDocumentPositionParams = textDocumentPosition(relativePath, position(line, column)) fun codeActionParams(relativePath: String, startLine: Int, startColumn: Int, endLine: Int, endColumn: Int, diagnostics: List, only: List): CodeActionParams { @@ -112,7 +113,7 @@ abstract class LanguageServerTestFixture( fun definitionParams(relativePath: String, position: Position): DefinitionParams = textDocumentPosition(relativePath, position).run { DefinitionParams(textDocument, position) } - fun textDocumentPosition(relativePath: String, position: Position): TextDocumentPositionParams { + private fun textDocumentPosition(relativePath: String, position: Position): TextDocumentPositionParams { val file = workspaceRoot.resolve(relativePath) val fileId = TextDocumentIdentifier(file.toUri().toString()) return TextDocumentPositionParams(fileId, position) @@ -123,7 +124,7 @@ abstract class LanguageServerTestFixture( fun range(startLine: Int, startColumn: Int, endLine: Int, endColumn: Int) = Range(position(startLine, startColumn), position(endLine, endColumn)) - fun uri(relativePath: String) = + fun uri(relativePath: String): URI = workspaceRoot.resolve(relativePath).toUri() fun referenceParams(relativePath: String, line: Int, column: Int): ReferenceParams = @@ -176,8 +177,8 @@ abstract class LanguageServerTestFixture( } fun testResourcesRoot(): Path { - val anchorTxt = LanguageServerTestFixture::class.java.getResource("/Anchor.txt").toURI() - return Paths.get(anchorTxt).parent!! + val anchorTxt = LanguageServerTestFixture::class.java.getResource("/Anchor.txt")?.toURI() + return anchorTxt?.let { Paths.get(it).parent } ?: throw RuntimeException("Could not find test resources root") } open class SingleFileTestFixture( @@ -189,6 +190,6 @@ open class SingleFileTestFixture( open(file) // Wait for lint, so subsequent replace(...) operations cause recovery - languageServer.textDocumentService.debounceLint.waitForPendingTask() + languageServer.textDocumentService.lintDebouncer.waitForPendingTask() } } diff --git a/shared/src/main/kotlin/org/javacs/kt/ScriptsConfiguration.kt b/shared/src/main/kotlin/org/javacs/kt/ScriptsConfiguration.kt index 50cb02d90..52c19cd0b 100644 --- a/shared/src/main/kotlin/org/javacs/kt/ScriptsConfiguration.kt +++ b/shared/src/main/kotlin/org/javacs/kt/ScriptsConfiguration.kt @@ -1,6 +1,6 @@ package org.javacs.kt -public data class ScriptsConfiguration( +data class ScriptsConfiguration( /** Whether .kts scripts are handled. */ var enabled: Boolean = false, /** Whether .gradle.kts scripts are handled. Only considered if scripts are enabled in general. */ diff --git a/shared/src/main/kotlin/org/javacs/kt/SourceExclusions.kt b/shared/src/main/kotlin/org/javacs/kt/SourceExclusions.kt index de4a512c2..373f5520b 100644 --- a/shared/src/main/kotlin/org/javacs/kt/SourceExclusions.kt +++ b/shared/src/main/kotlin/org/javacs/kt/SourceExclusions.kt @@ -1,11 +1,9 @@ package org.javacs.kt import org.javacs.kt.util.filePath -import java.io.File import java.net.URI import java.nio.file.FileSystems import java.nio.file.Path -import java.nio.file.Paths // TODO: Read exclusions from gitignore/settings.json/... instead of // hardcoding them diff --git a/shared/src/main/kotlin/org/javacs/kt/classpath/BackupClassPathResolver.kt b/shared/src/main/kotlin/org/javacs/kt/classpath/BackupClassPathResolver.kt index c8b6d6b45..6b20bf38a 100644 --- a/shared/src/main/kotlin/org/javacs/kt/classpath/BackupClassPathResolver.kt +++ b/shared/src/main/kotlin/org/javacs/kt/classpath/BackupClassPathResolver.kt @@ -109,7 +109,7 @@ private fun compareVersions(left: Path, right: Path): Int { val leftVersion = extractVersion(left) val rightVersion = extractVersion(right) - for (i in 0 until Math.min(leftVersion.size, rightVersion.size)) { + for (i in 0 until leftVersion.size.coerceAtMost(rightVersion.size)) { val leftRev = leftVersion[i].reversed() val rightRev = rightVersion[i].reversed() val compare = leftRev.compareTo(rightRev) diff --git a/shared/src/main/kotlin/org/javacs/kt/classpath/ClassPathResolver.kt b/shared/src/main/kotlin/org/javacs/kt/classpath/ClassPathResolver.kt index d7641f102..3455c4613 100644 --- a/shared/src/main/kotlin/org/javacs/kt/classpath/ClassPathResolver.kt +++ b/shared/src/main/kotlin/org/javacs/kt/classpath/ClassPathResolver.kt @@ -14,17 +14,17 @@ interface ClassPathResolver { classpath } catch (e: Exception) { LOG.warn("Could not resolve classpath using {}: {}", resolverType, e.message) - emptySet() + emptySet() } val buildScriptClasspath: Set - get() = emptySet() + get() = emptySet() val buildScriptClasspathOrEmpty: Set get() = try { buildScriptClasspath } catch (e: Exception) { LOG.warn("Could not resolve buildscript classpath using {}: {}", resolverType, e.message) - emptySet() + emptySet() } val classpathWithSources: Set get() = classpath diff --git a/shared/src/main/kotlin/org/javacs/kt/classpath/GradleClassPathResolver.kt b/shared/src/main/kotlin/org/javacs/kt/classpath/GradleClassPathResolver.kt index 1e0cbc7b3..fb9e9a9b9 100644 --- a/shared/src/main/kotlin/org/javacs/kt/classpath/GradleClassPathResolver.kt +++ b/shared/src/main/kotlin/org/javacs/kt/classpath/GradleClassPathResolver.kt @@ -53,8 +53,8 @@ private fun gradleScriptToTempFile(scriptName: String, deleteOnExit: Boolean = f LOG.debug("Creating temporary gradle file {}", config.absolutePath) config.bufferedWriter().use { configWriter -> - GradleClassPathResolver::class.java.getResourceAsStream("/$scriptName").bufferedReader().use { configReader -> - configReader.copyTo(configWriter) + GradleClassPathResolver::class.java.getResourceAsStream("/$scriptName")?.bufferedReader().use { configReader -> + configReader?.copyTo(configWriter) ?: throw KotlinLSException("Could not find resource '$scriptName'") } } @@ -66,23 +66,21 @@ private fun getGradleCommand(workspace: Path): Path { val wrapper = workspace.resolve(wrapperName).toAbsolutePath() if (Files.isExecutable(wrapper)) { return wrapper - } else { - return workspace.parent?.let(::getGradleCommand) - ?: findCommandOnPath("gradle") - ?: throw KotlinLSException("Could not find 'gradle' on PATH") } + return workspace.parent?.let(::getGradleCommand) + ?: findCommandOnPath("gradle") + ?: throw KotlinLSException("Could not find 'gradle' on PATH") } private fun readDependenciesViaGradleCLI(projectDirectory: Path, gradleScripts: List, gradleTasks: List): Set { LOG.info("Resolving dependencies for '{}' through Gradle's CLI using tasks {}...", projectDirectory.fileName, gradleTasks) - val tmpScripts = gradleScripts.map { gradleScriptToTempFile(it, deleteOnExit = false).toPath().toAbsolutePath() } + val tmpScripts = gradleScripts.map { gradleScriptToTempFile(it).toPath().toAbsolutePath() } val gradle = getGradleCommand(projectDirectory) val command = listOf(gradle.toString()) + tmpScripts.flatMap { listOf("-I", it.toString()) } + gradleTasks + listOf("--console=plain") val dependencies = findGradleCLIDependencies(command, projectDirectory) - ?.also { LOG.debug("Classpath for task {}", it) } - .orEmpty() + .also { LOG.debug("Classpath for task {}", it) } .filter { it.toString().lowercase().endsWith(".jar") || Files.isDirectory(it) } // Some Gradle plugins seem to cause this to output POMs, therefore filter JARs .toSet() @@ -90,7 +88,7 @@ private fun readDependenciesViaGradleCLI(projectDirectory: Path, gradleScripts: return dependencies } -private fun findGradleCLIDependencies(command: List, projectDirectory: Path): Set? { +private fun findGradleCLIDependencies(command: List, projectDirectory: Path): Set { val (result, errors) = execAndReadStdoutAndStderr(command, projectDirectory) if ("FAILURE: Build failed" in errors) { LOG.warn("Gradle task failed: {}", errors) @@ -104,13 +102,11 @@ private fun findGradleCLIDependencies(command: List, projectDirectory: P return parseGradleCLIDependencies(result) } -private val artifactPattern by lazy { "kotlin-lsp-gradle (.+)(?:\r?\n)".toRegex() } -private val gradleErrorWherePattern by lazy { "\\*\\s+Where:[\r\n]+(\\S\\.*)".toRegex() } +private val artifactPattern by lazy { "kotlin-lsp-gradle (.+)\r?\n".toRegex() } -private fun parseGradleCLIDependencies(output: String): Set? { +private fun parseGradleCLIDependencies(output: String): Set { LOG.debug(output) val artifacts = artifactPattern.findAll(output) - .mapNotNull { Paths.get(it.groups[1]?.value) } - .filterNotNull() + .mapNotNull { it.groups[1]?.value?.let { it1 -> Paths.get(it1) } } return artifacts.toSet() } diff --git a/shared/src/main/kotlin/org/javacs/kt/classpath/Home.kt b/shared/src/main/kotlin/org/javacs/kt/classpath/Home.kt index b8c236e9b..a58669acd 100644 --- a/shared/src/main/kotlin/org/javacs/kt/classpath/Home.kt +++ b/shared/src/main/kotlin/org/javacs/kt/classpath/Home.kt @@ -3,7 +3,6 @@ package org.javacs.kt.classpath import java.nio.file.Files import java.nio.file.Path import java.nio.file.Paths -import org.javacs.kt.util.KotlinLSException import org.javacs.kt.util.userHome private fun createPathOrNull(envVar: String): Path? = System.getenv(envVar)?.let(Paths::get) @@ -11,8 +10,8 @@ private fun createPathOrNull(envVar: String): Path? = System.getenv(envVar)?.let private val possibleMavenRepositoryPaths = sequenceOf( createPathOrNull("MAVEN_REPOSITORY"), - createPathOrNull("MAVEN_HOME")?.let { it.resolve("repository") }, - createPathOrNull("M2_HOME")?.let { it.resolve("repository") }, + createPathOrNull("MAVEN_HOME")?.resolve("repository"), + createPathOrNull("M2_HOME")?.resolve("repository"), userHome.resolve(".m2/repository"), ) .filterNotNull() diff --git a/shared/src/main/kotlin/org/javacs/kt/classpath/MavenClassPathResolver.kt b/shared/src/main/kotlin/org/javacs/kt/classpath/MavenClassPathResolver.kt index a34bbccb1..4e7748cc3 100644 --- a/shared/src/main/kotlin/org/javacs/kt/classpath/MavenClassPathResolver.kt +++ b/shared/src/main/kotlin/org/javacs/kt/classpath/MavenClassPathResolver.kt @@ -1,6 +1,7 @@ package org.javacs.kt.classpath import org.javacs.kt.LOG +import org.javacs.kt.util.KotlinLSException import org.javacs.kt.util.findCommandOnPath import org.javacs.kt.util.findProjectCommandWithName import org.javacs.kt.util.execAndReadStdoutAndStderr @@ -93,7 +94,7 @@ private fun findMavenArtifact(a: Artifact, source: Boolean): Path? { ?.resolve(a.version) ?.resolve(mavenJarName(a, source)) - return if (Files.exists(result)) + return if (result?.let { Files.exists(it) } == true) result else { LOG.warn("Couldn't find {} in {}", a, result) @@ -134,9 +135,8 @@ private val mvnCommandFromPath: Path? by lazy { } private fun mvnCommand(pom: Path): Path { - return requireNotNull(mvnCommandFromPath ?: findProjectCommandWithName("mvnw", pom)?.also { - LOG.info("Using mvn wrapper (mvnw) in place of mvn command") - }) { "Unable to find the 'mvn' command or suitable wrapper" } + return mvnCommandFromPath ?: findProjectCommandWithName("mvnw", pom) + ?: throw KotlinLSException("Unable to find the 'mvn' command or suitable wrapper") } fun parseMavenArtifact(rawArtifact: String, version: String? = null): Artifact { diff --git a/shared/src/main/kotlin/org/javacs/kt/classpath/WithStdlibResolver.kt b/shared/src/main/kotlin/org/javacs/kt/classpath/WithStdlibResolver.kt index bbbcccefa..ef92104ed 100644 --- a/shared/src/main/kotlin/org/javacs/kt/classpath/WithStdlibResolver.kt +++ b/shared/src/main/kotlin/org/javacs/kt/classpath/WithStdlibResolver.kt @@ -38,11 +38,11 @@ private fun wrapWithStdlib(paths: Set): Set { ).first().path } - val stdlibs = linkedStdLibs.ifEmpty { + val stdLibs = linkedStdLibs.ifEmpty { findKotlinStdlib()?.let { listOf(it) } ?: listOf() } - return paths.filterNot(isStdlib).union(stdlibs) + return paths.filterNot(isStdlib).union(stdLibs) } private data class StdLibItem( diff --git a/shared/src/main/kotlin/org/javacs/kt/util/AsyncExecutor.kt b/shared/src/main/kotlin/org/javacs/kt/util/AsyncExecutor.kt index b794fae07..05dd4e4c5 100644 --- a/shared/src/main/kotlin/org/javacs/kt/util/AsyncExecutor.kt +++ b/shared/src/main/kotlin/org/javacs/kt/util/AsyncExecutor.kt @@ -1,37 +1,43 @@ package org.javacs.kt.util import org.javacs.kt.LOG -import java.time.Duration -import java.util.function.Supplier import java.util.concurrent.CompletableFuture import java.util.concurrent.Executors import java.util.concurrent.TimeUnit -private var threadCount = 0 +class AsyncExecutor(private val name: String) { + private val workerThread = Executors.newSingleThreadExecutor { runnable -> + Thread(runnable, "kls-executor-${name}").apply { + isDaemon = true + } + } -class AsyncExecutor { - private val workerThread = Executors.newSingleThreadExecutor { Thread(it, "async${threadCount++}") } + /** + * Executes a task asynchronously without returning a result + */ + fun execute(task: () -> Unit): CompletableFuture = + CompletableFuture.runAsync({ task() }, workerThread) - fun execute(task: () -> Unit) = - CompletableFuture.runAsync(Runnable(task), workerThread) + /** + * Executes a task asynchronously and returns a result + */ + fun compute(task: () -> R): CompletableFuture = + CompletableFuture.supplyAsync({ task() }, workerThread) - fun compute(task: () -> R) = - CompletableFuture.supplyAsync(Supplier(task), workerThread) + /** + * Shuts down the executor + * @param awaitTermination if true, waits for all tasks to complete + */ + fun shutdown(awaitTermination: Boolean) { + workerThread.shutdown() + if (awaitTermination) { + LOG.info {"Awaiting async termination of kls executor..."} + workerThread.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS) + } + } - fun computeOr(defaultValue: R, task: () -> R?) = - CompletableFuture.supplyAsync(Supplier { - try { - task() ?: defaultValue - } catch (e: Exception) { - defaultValue - } - }, workerThread) - - fun shutdown(awaitTermination: Boolean) { - workerThread.shutdown() - if (awaitTermination) { - LOG.info("Awaiting async termination...") - workerThread.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS) - } - } + /** + * Attempts to shut down executor immediately, cancelling running tasks + */ + fun shutdownNow(): List = workerThread.shutdownNow() } diff --git a/shared/src/main/kotlin/org/javacs/kt/util/Debouncer.kt b/shared/src/main/kotlin/org/javacs/kt/util/Debouncer.kt index 21916ac7b..d883eff08 100644 --- a/shared/src/main/kotlin/org/javacs/kt/util/Debouncer.kt +++ b/shared/src/main/kotlin/org/javacs/kt/util/Debouncer.kt @@ -2,18 +2,16 @@ package org.javacs.kt.util import org.javacs.kt.LOG import java.time.Duration -import java.util.function.Supplier import java.util.concurrent.atomic.AtomicReference import java.util.concurrent.ScheduledExecutorService import java.util.concurrent.Executors import java.util.concurrent.TimeUnit -import java.util.concurrent.CompletableFuture import java.util.concurrent.Future private var threadCount = 0 class Debouncer( - private val delay: Duration, + delay: Duration, private val executor: ScheduledExecutorService = Executors.newScheduledThreadPool(1) { Thread(it, "debounce${threadCount++}") } @@ -24,7 +22,7 @@ class Debouncer( fun submitImmediately(task: (cancelCallback: () -> Boolean) -> Unit) { pendingTask?.cancel(false) val currentTaskRef = AtomicReference>() - val currentTask = executor.submit { task { currentTaskRef.get()?.isCancelled() ?: false } } + val currentTask = executor.submit { task { currentTaskRef.get()?.isCancelled ?: false } } currentTaskRef.set(currentTask) pendingTask = currentTask } @@ -32,7 +30,7 @@ class Debouncer( fun schedule(task: (cancelCallback: () -> Boolean) -> Unit) { pendingTask?.cancel(false) val currentTaskRef = AtomicReference>() - val currentTask = executor.schedule({ task { currentTaskRef.get()?.isCancelled() ?: false } }, delayMs, TimeUnit.MILLISECONDS) + val currentTask = executor.schedule({ task { currentTaskRef.get()?.isCancelled ?: false } }, delayMs, TimeUnit.MILLISECONDS) currentTaskRef.set(currentTask) pendingTask = currentTask } diff --git a/shared/src/main/kotlin/org/javacs/kt/util/DelegatePrintStream.kt b/shared/src/main/kotlin/org/javacs/kt/util/DelegatePrintStream.kt index 598c85f83..221b14059 100644 --- a/shared/src/main/kotlin/org/javacs/kt/util/DelegatePrintStream.kt +++ b/shared/src/main/kotlin/org/javacs/kt/util/DelegatePrintStream.kt @@ -2,7 +2,6 @@ package org.javacs.kt.util import java.io.ByteArrayOutputStream import java.io.PrintStream -import java.util.function.Consumer class DelegatePrintStream(private val delegate: (String) -> Unit): PrintStream(ByteArrayOutputStream(0)) { private val newLine = System.lineSeparator() @@ -10,7 +9,7 @@ class DelegatePrintStream(private val delegate: (String) -> Unit): PrintStream(B override fun write(c: Int) = delegate((c.toChar()).toString()) override fun write(buf: ByteArray, off: Int, len: Int) { - if (len > 0 && buf.size > 0) { + if (len > 0 && buf.isNotEmpty()) { delegate(String(buf, off, len)) } } diff --git a/shared/src/main/kotlin/org/javacs/kt/util/ExitingInputStream.kt b/shared/src/main/kotlin/org/javacs/kt/util/ExitingInputStream.kt index 6919d92f8..f73a2c471 100644 --- a/shared/src/main/kotlin/org/javacs/kt/util/ExitingInputStream.kt +++ b/shared/src/main/kotlin/org/javacs/kt/util/ExitingInputStream.kt @@ -2,6 +2,7 @@ package org.javacs.kt.util import java.io.InputStream import org.javacs.kt.LOG +import kotlin.system.exitProcess class ExitingInputStream(private val delegate: InputStream): InputStream() { override fun read(): Int = exitIfNegative { delegate.read() } @@ -15,7 +16,7 @@ class ExitingInputStream(private val delegate: InputStream): InputStream() { if (result < 0) { LOG.info("System.in has closed, exiting") - System.exit(0) + exitProcess(0) } return result diff --git a/shared/src/main/kotlin/org/javacs/kt/util/KotlinLSException.kt b/shared/src/main/kotlin/org/javacs/kt/util/KotlinLSException.kt index c067945b5..bfc4a4c20 100644 --- a/shared/src/main/kotlin/org/javacs/kt/util/KotlinLSException.kt +++ b/shared/src/main/kotlin/org/javacs/kt/util/KotlinLSException.kt @@ -1,7 +1,4 @@ package org.javacs.kt.util -class KotlinLSException : RuntimeException { - constructor(msg: String) : super(msg) {} - - constructor(msg: String, cause: Throwable) : super(msg, cause) {} +class KotlinLSException(msg: String) : RuntimeException(msg) { } diff --git a/shared/src/main/kotlin/org/javacs/kt/util/StringUtils.kt b/shared/src/main/kotlin/org/javacs/kt/util/StringUtils.kt index 4e7a8759c..e08c5a440 100644 --- a/shared/src/main/kotlin/org/javacs/kt/util/StringUtils.kt +++ b/shared/src/main/kotlin/org/javacs/kt/util/StringUtils.kt @@ -15,8 +15,8 @@ package org.javacs.kt.util * @param maxOffset The number of characters to search for matching letters */ fun stringDistance(candidate: CharSequence, pattern: CharSequence, maxOffset: Int = 4): Int = when { - candidate.length == 0 -> pattern.length - pattern.length == 0 -> candidate.length + candidate.isEmpty() -> pattern.length + pattern.isEmpty() -> candidate.length else -> { val candidateLength = candidate.length val patternLength = pattern.length diff --git a/shared/src/main/kotlin/org/javacs/kt/util/Utils.kt b/shared/src/main/kotlin/org/javacs/kt/util/Utils.kt index 36907d605..6f0e4f2ab 100644 --- a/shared/src/main/kotlin/org/javacs/kt/util/Utils.kt +++ b/shared/src/main/kotlin/org/javacs/kt/util/Utils.kt @@ -4,13 +4,6 @@ import org.javacs.kt.LOG import java.io.PrintStream import java.nio.file.Path import java.nio.file.Paths -import java.util.concurrent.CompletableFuture - -fun execAndReadStdout(shellCommand: List, directory: Path): String { - val process = ProcessBuilder(shellCommand).directory(directory.toFile()).start() - val stdout = process.inputStream - return stdout.bufferedReader().use { it.readText() } -} fun execAndReadStdoutAndStderr(shellCommand: List, directory: Path): Pair { val process = ProcessBuilder(shellCommand).directory(directory.toFile()).start() @@ -34,14 +27,13 @@ inline fun withCustomStdout(delegateOut: PrintStream, task: () -> Unit) { System.setOut(actualOut) } -fun winCompatiblePathOf(path: String): Path { +fun winCompatiblePathOf(path: String): Path = if (path.get(2) == ':' && path.get(0) == '/') { // Strip leading '/' when dealing with paths on Windows - return Paths.get(path.substring(1)) + Paths.get(path.substring(1)) } else { - return Paths.get(path) + Paths.get(path) } -} fun String.partitionAroundLast(separator: String): Pair = lastIndexOf(separator) .let { Pair(substring(0, it), substring(it, length)) } @@ -53,10 +45,8 @@ fun Path.replaceExtensionWith(newExtension: String): Path { } inline fun > C.onEachIndexed(transform: (index: Int, T) -> Unit): C = apply { - var i = 0 - for (element in this) { + for ((i, element) in this.withIndex()) { transform(i, element) - i++ } } @@ -65,27 +55,10 @@ fun noResult(message: String, result: T): T { return result } -fun noFuture(message: String, contents: T): CompletableFuture = noResult(message, CompletableFuture.completedFuture(contents)) - fun emptyResult(message: String): List = noResult(message, emptyList()) fun nullResult(message: String): T? = noResult(message, null) -fun firstNonNull(vararg optionals: () -> T?): T? { - for (optional in optionals) { - val result = optional() - if (result != null) { - return result - } - } - return null -} - -fun nonNull(item: T?, errorMsgIfNull: String): T = - if (item == null) { - throw NullPointerException(errorMsgIfNull) - } else item - inline fun tryResolving(what: String, resolver: () -> T?): T? { try { val resolved = resolver()