Skip to content

Commit 4dd96c7

Browse files
committed
Run analysis for whole project in background
1 parent a4bf4bd commit 4dd96c7

File tree

5 files changed

+124
-27
lines changed

5 files changed

+124
-27
lines changed

kotlin-bundled-compiler/META-INF/MANIFEST.MF

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,4 +408,8 @@ Export-Package: com.google.common.base,
408408
org.picocontainer.monitors,
409409
src.org.jetbrains.kotlin.idea.codeInsight,
410410
src.org.jetbrains.kotlin.idea.util,
411-
src.org.jetbrains.kotlin.resolve.lazy
411+
src.org.jetbrains.kotlin.resolve.lazy,
412+
org.jetbrains.kotlin.idea.resolve,
413+
org.jetbrains.kotlin.resolve.scopes.utils,
414+
org.jetbrains.kotlin.fileClasses,
415+
org.jetbrains.kotlin.progress

kotlin-eclipse-ui/META-INF/MANIFEST.MF

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ Import-Package: com.intellij.navigation,
4848
org.jetbrains.kotlin.j2k,
4949
org.eclipse.ui.texteditor.link,
5050
org.eclipse.jdt.internal.compiler.env,
51-
org.eclipse.jdt.core.compiler
51+
org.eclipse.jdt.core.compiler,
52+
org.jetbrains.kotlin.progress
5253
Bundle-RequiredExecutionEnvironment: JavaSE-1.7
5354
Export-Package: org.jetbrains.kotlin.eclipse.ui.utils,
5455
org.jetbrains.kotlin.ui,
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/*******************************************************************************
2+
* Copyright 2000-2015 JetBrains s.r.o.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*******************************************************************************/
17+
package org.jetbrains.kotlin.ui.builder
18+
19+
import org.eclipse.core.runtime.jobs.Job
20+
import org.eclipse.core.runtime.IProgressMonitor
21+
import org.eclipse.core.runtime.IStatus
22+
import org.eclipse.core.runtime.Status
23+
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
24+
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
25+
import org.jetbrains.kotlin.progress.CompilationCanceledException
26+
import org.eclipse.jdt.core.IJavaProject
27+
import org.eclipse.core.runtime.NullProgressMonitor
28+
import org.jetbrains.kotlin.core.model.KotlinAnalysisProjectCache
29+
import org.eclipse.core.resources.IFile
30+
import org.jetbrains.kotlin.core.builder.KotlinPsiManager
31+
32+
public class KotlinAnalysisJob(
33+
private val javaProject: IJavaProject,
34+
private val affectedFiles: List<IFile>) : Job("Kotlin Analysis") {
35+
init {
36+
setPriority(DECORATE)
37+
38+
ProgressIndicatorAndCompilationCanceledStatus.setCompilationCanceledStatus(object : CompilationCanceledStatus {
39+
override fun checkCanceled() {
40+
if (canceled) throw CompilationCanceledException()
41+
}
42+
})
43+
}
44+
45+
val familyIndicator = constructFamilyIndicator(javaProject)
46+
47+
@Volatile var canceled = false
48+
49+
override fun run(monitor: IProgressMonitor): IStatus {
50+
try {
51+
canceled = false
52+
53+
val analysisResult = KotlinAnalysisProjectCache.getAnalysisResult(javaProject)
54+
val projectFiles = KotlinPsiManager.INSTANCE.getFilesByProject(javaProject.project)
55+
updateLineMarkers(analysisResult.bindingContext.diagnostics, (projectFiles - affectedFiles).toList())
56+
57+
return Status.OK_STATUS
58+
} catch (e: CompilationCanceledException) {
59+
canceled = false
60+
61+
return Status.CANCEL_STATUS
62+
}
63+
}
64+
65+
override fun belongsTo(family: Any): Boolean = family == familyIndicator
66+
67+
override fun canceling() {
68+
super.canceling()
69+
canceled = true
70+
}
71+
}
72+
73+
private fun constructFamilyIndicator(javaProject: IJavaProject): String {
74+
return javaProject.getProject().getName() + "_kotlinAnalysisFamily"
75+
}
76+
77+
fun runCancellableAnalysisFor(javaProject: IJavaProject, affectedFiles: List<IFile>) {
78+
val family = constructFamilyIndicator(javaProject)
79+
Job.getJobManager().cancel(family)
80+
Job.getJobManager().join(family, NullProgressMonitor()) // It should be fast enough
81+
82+
KotlinAnalysisJob(javaProject, affectedFiles).schedule()
83+
}

kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/builder/KotlinBuilder.kt

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,17 @@ import org.jetbrains.kotlin.ui.editors.annotations.AnnotationManager
3939
import org.jetbrains.kotlin.ui.editors.annotations.DiagnosticAnnotation
4040
import org.jetbrains.kotlin.ui.editors.annotations.DiagnosticAnnotationUtil
4141
import com.google.common.collect.Sets
42+
import org.jetbrains.kotlin.core.resolve.KotlinAnalyzer
43+
import org.eclipse.core.resources.IMarker
44+
import org.eclipse.core.runtime.jobs.Job
45+
import org.eclipse.core.runtime.IStatus
46+
import org.eclipse.core.runtime.Status
47+
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
48+
import org.jetbrains.kotlin.progress.CompilationCanceledStatus
49+
import org.jetbrains.kotlin.progress.CompilationCanceledException
4250

4351
class KotlinBuilder : IncrementalProjectBuilder() {
4452
override fun build(kind: Int, args: Map<String, String>?, monitor: IProgressMonitor?): Array<IProject>? {
45-
val project = getProject()
4653
val javaProject = JavaCore.create(project)
4754
if (isBuildingForLaunch()) {
4855
compileKotlinFiles(javaProject)
@@ -56,24 +63,25 @@ class KotlinBuilder : IncrementalProjectBuilder() {
5663
if (delta != null) getAffectedFiles(delta, javaProject) else emptySet()
5764
}
5865

59-
commitFiles(affectedFiles)
66+
val existingAffectedFiles = affectedFiles.filter { it.exists() }
67+
68+
commitFiles(existingAffectedFiles)
6069

6170
if (affectedFiles.isNotEmpty()) {
6271
KotlinLightClassGeneration.updateLightClasses(javaProject, affectedFiles)
6372
}
6473

65-
val analysisResult = KotlinAnalysisProjectCache.getAnalysisResult(javaProject)
66-
updateLineMarkers(analysisResult.bindingContext.diagnostics)
74+
val ktFiles = existingAffectedFiles.map { KotlinPsiManager.INSTANCE.getParsedFile(it) }
75+
val analysisResult = KotlinAnalyzer.analyzeFiles(javaProject, ktFiles).analysisResult
76+
updateLineMarkers(analysisResult.bindingContext.diagnostics, existingAffectedFiles)
77+
78+
runCancellableAnalysisFor(javaProject, existingAffectedFiles)
6779

6880
return null
6981
}
7082

7183
private fun commitFiles(files: Collection<IFile>) {
72-
for (file in files) {
73-
if (file.exists()) {
74-
KotlinPsiManager.getKotlinFileIfExist(file, EditorUtil.getDocument(file).get())
75-
}
76-
}
84+
files.forEach { KotlinPsiManager.getKotlinFileIfExist(it, EditorUtil.getDocument(it).get()) }
7785
}
7886

7987
private fun getAffectedFiles(resourceDelta: IResourceDelta, javaProject: IJavaProject): Set<IFile> {
@@ -100,27 +108,27 @@ class KotlinBuilder : IncrementalProjectBuilder() {
100108
return Thread.currentThread().getStackTrace().find { it.className == launchDelegateFQName } != null
101109
}
102110

103-
private fun compileKotlinFiles(javaProject:IJavaProject) {
111+
private fun compileKotlinFiles(javaProject: IJavaProject) {
104112
val compilerResult = KotlinCompilerUtils.compileWholeProject(javaProject)
105113
if (!compilerResult.compiledCorrectly()) {
106114
KotlinCompilerUtils.handleCompilerOutput(compilerResult.getCompilerOutput())
107115
}
108116
}
117+
}
118+
119+
fun updateLineMarkers(diagnostics: Diagnostics, affectedFiles: List<IFile>) {
120+
clearMarkersFromFiles(affectedFiles)
121+
addMarkersToProject(DiagnosticAnnotationUtil.INSTANCE.handleDiagnostics(diagnostics), affectedFiles)
122+
}
123+
124+
private fun clearMarkersFromFiles(files: List<IFile>) {
125+
files.forEach { it.deleteMarkers(IMarker.PROBLEM, true, IResource.DEPTH_INFINITE) }
126+
}
127+
128+
private fun addMarkersToProject(annotations: Map<IFile, List<DiagnosticAnnotation>>, affectedFiles: List<IFile>) {
129+
affectedFiles.forEach { DiagnosticAnnotationUtil.INSTANCE.addParsingDiagnosticAnnotations(it, annotations) }
109130

110-
private fun updateLineMarkers(diagnostics:Diagnostics) {
111-
addMarkersToProject(DiagnosticAnnotationUtil.INSTANCE.handleDiagnostics(diagnostics), getProject())
112-
}
113-
114-
private fun addMarkersToProject(annotations: Map<IFile, List<DiagnosticAnnotation>>, project: IProject) {
115-
AnnotationManager.clearAllMarkersFromProject(project)
116-
for (file in KotlinPsiManager.INSTANCE.getFilesByProject(getProject())) {
117-
DiagnosticAnnotationUtil.INSTANCE.addParsingDiagnosticAnnotations(file, annotations)
118-
}
119-
120-
for ((file, diagnosticAnnotations) in annotations) {
121-
for (annotation in diagnosticAnnotations) {
122-
AnnotationManager.addProblemMarker(annotation, file)
123-
}
124-
}
131+
for (file in affectedFiles) {
132+
annotations[file]?.forEach { AnnotationManager.addProblemMarker(it, file) }
125133
}
126134
}

kotlin-eclipse-ui/src/org/jetbrains/kotlin/ui/editors/annotations/AnnotationManager.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@ object KotlinLineAnnotationsReconciler : KotlinReconcilingListener {
140140

141141
val diagnostics = KotlinAnalyzer.analyzeFile(editor.javaProject!!, jetFile).analysisResult.bindingContext.diagnostics
142142
val annotations = DiagnosticAnnotationUtil.INSTANCE.handleDiagnostics(diagnostics)
143+
143144
DiagnosticAnnotationUtil.INSTANCE.addParsingDiagnosticAnnotations(file, annotations)
144145
DiagnosticAnnotationUtil.INSTANCE.updateAnnotations(editor, annotations)
145146
}

0 commit comments

Comments
 (0)