- Out of block modification strategy for Kotlin block expression
- Separate project analysis for IDEA needs: headers + bodies
This commit is contained in:
@@ -33,6 +33,8 @@ import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
|
||||
import org.jetbrains.jet.lang.diagnostics.Errors;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTraceContext;
|
||||
import org.jetbrains.jet.lang.resolve.BodiesResolveContext;
|
||||
import org.jetbrains.jet.lang.resolve.DelegatingBindingTrace;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
@@ -44,7 +46,9 @@ public final class AnalyzerFacadeWithCache {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache");
|
||||
|
||||
private final static Key<CachedValue<AnalyzeExhaust>> ANALYZE_EXHAUST = Key.create("ANALYZE_EXHAUST");
|
||||
private final static Key<CachedValue<AnalyzeExhaust>> ANALYZE_EXHAUST_HEADERS = Key.create("ANALYZE_EXHAUST_HEADERS");
|
||||
private final static Key<CachedValue<AnalyzeExhaust>> ANALYZE_EXHAUST_FULL = Key.create("ANALYZE_EXHAUST_FULL");
|
||||
|
||||
private static final Object lock = new Object();
|
||||
public static final Function<JetFile, Collection<JetFile>> SINGLE_DECLARATION_PROVIDER = new Function<JetFile, Collection<JetFile>>() {
|
||||
@Override
|
||||
@@ -64,48 +68,87 @@ public final class AnalyzerFacadeWithCache {
|
||||
* @param declarationProvider
|
||||
* @return
|
||||
*/
|
||||
// TODO: Also need to pass several files when user have multi-file environment
|
||||
@NotNull
|
||||
public static AnalyzeExhaust analyzeFileWithCache(@NotNull final JetFile file,
|
||||
@NotNull final Function<JetFile, Collection<JetFile>> declarationProvider) {
|
||||
// Need lock for getValue(), because parallel threads can start evaluation of compute() simultaneously
|
||||
synchronized (lock) {
|
||||
CachedValue<AnalyzeExhaust> bindingContextCachedValue = file.getUserData(ANALYZE_EXHAUST);
|
||||
CachedValue<AnalyzeExhaust> bindingContextCachedValue = file.getUserData(ANALYZE_EXHAUST_FULL);
|
||||
if (bindingContextCachedValue == null) {
|
||||
bindingContextCachedValue =
|
||||
CachedValuesManager.getManager(file.getProject()).createCachedValue(new CachedValueProvider<AnalyzeExhaust>() {
|
||||
@Override
|
||||
public Result<AnalyzeExhaust> compute() {
|
||||
try {
|
||||
AnalyzeExhaust exhaust = AnalyzerFacadeProvider.getAnalyzerFacadeForFile(file)
|
||||
.analyzeFiles(file.getProject(),
|
||||
declarationProvider.fun(file),
|
||||
Predicates.<PsiFile>equalTo(file),
|
||||
JetControlFlowDataTraceFactory.EMPTY);
|
||||
return new Result<AnalyzeExhaust>(exhaust, PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
handleError(e);
|
||||
return emptyExhaustWithDiagnosticOnFile(e);
|
||||
}
|
||||
}
|
||||
CachedValuesManager.getManager(file.getProject()).createCachedValue(new CachedValueProvider<AnalyzeExhaust>() {
|
||||
@Override
|
||||
public Result<AnalyzeExhaust> compute() {
|
||||
try {
|
||||
// System.out.println("===============ReCache - In-Block==============");
|
||||
|
||||
@NotNull
|
||||
private Result<AnalyzeExhaust> emptyExhaustWithDiagnosticOnFile(Throwable e) {
|
||||
BindingTraceContext bindingTraceContext = new BindingTraceContext();
|
||||
bindingTraceContext.report(Errors.EXCEPTION_WHILE_ANALYZING.on(file, e));
|
||||
AnalyzeExhaust analyzeExhaust = AnalyzeExhaust.error(bindingTraceContext.getBindingContext(), e);
|
||||
return new Result<AnalyzeExhaust>(analyzeExhaust, PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
}, false);
|
||||
file.putUserData(ANALYZE_EXHAUST, bindingContextCachedValue);
|
||||
// Collect context for headers first
|
||||
Collection<JetFile> allFilesToAnalyze = declarationProvider.fun(file);
|
||||
AnalyzeExhaust analyzeExhaustHeaders = analyzeHeadersWithCacheOnFile(file, allFilesToAnalyze);
|
||||
|
||||
BodiesResolveContext context = analyzeExhaustHeaders.getBodiesResolveContext();
|
||||
assert context != null : "Headers resolver should prepare and stored information for bodies resolve";
|
||||
|
||||
// Need to resolve bodies in given file
|
||||
AnalyzeExhaust exhaust = AnalyzerFacadeProvider.getAnalyzerFacadeForFile(file).analyzeBodiesInFiles(
|
||||
file.getProject(),
|
||||
Predicates.<PsiFile>equalTo(file),
|
||||
JetControlFlowDataTraceFactory.EMPTY,
|
||||
new DelegatingBindingTrace(analyzeExhaustHeaders.getBindingContext()),
|
||||
context);
|
||||
|
||||
return new Result<AnalyzeExhaust>(exhaust, PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Throwable e) {
|
||||
handleError(e);
|
||||
return emptyExhaustWithDiagnosticOnFile(e);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Result<AnalyzeExhaust> emptyExhaustWithDiagnosticOnFile(Throwable e) {
|
||||
BindingTraceContext bindingTraceContext = new BindingTraceContext();
|
||||
bindingTraceContext.report(Errors.EXCEPTION_WHILE_ANALYZING.on(file, e));
|
||||
AnalyzeExhaust analyzeExhaust = AnalyzeExhaust.error(bindingTraceContext.getBindingContext(), e);
|
||||
return new Result<AnalyzeExhaust>(analyzeExhaust, PsiModificationTracker.MODIFICATION_COUNT);
|
||||
}
|
||||
}, false);
|
||||
|
||||
file.putUserData(ANALYZE_EXHAUST_FULL, bindingContextCachedValue);
|
||||
}
|
||||
|
||||
return bindingContextCachedValue.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
private static AnalyzeExhaust analyzeHeadersWithCacheOnFile(@NotNull final JetFile fileToCache,
|
||||
@NotNull final Collection<JetFile> headerFiles) {
|
||||
CachedValue<AnalyzeExhaust> bindingContextCachedValue = fileToCache.getUserData(ANALYZE_EXHAUST_HEADERS);
|
||||
if (bindingContextCachedValue == null) {
|
||||
bindingContextCachedValue =
|
||||
CachedValuesManager.getManager(fileToCache.getProject()).createCachedValue(new CachedValueProvider<AnalyzeExhaust>() {
|
||||
@Override
|
||||
public Result<AnalyzeExhaust> compute() {
|
||||
// System.out.println("===============ReCache - OUT-OF-BLOCK==============");
|
||||
AnalyzeExhaust exhaust = AnalyzerFacadeProvider.getAnalyzerFacadeForFile(fileToCache)
|
||||
.analyzeFiles(fileToCache.getProject(),
|
||||
headerFiles,
|
||||
Predicates.<PsiFile>alwaysFalse(),
|
||||
JetControlFlowDataTraceFactory.EMPTY);
|
||||
|
||||
return new Result<AnalyzeExhaust>(exhaust, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
|
||||
}
|
||||
}, false);
|
||||
fileToCache.putUserData(ANALYZE_EXHAUST_HEADERS, bindingContextCachedValue);
|
||||
}
|
||||
|
||||
return bindingContextCachedValue.getValue();
|
||||
}
|
||||
|
||||
private static void handleError(@NotNull Throwable e) {
|
||||
DiagnosticUtils.throwIfRunningOnServer(e);
|
||||
LOG.error(e);
|
||||
|
||||
@@ -24,8 +24,8 @@ import org.jetbrains.jet.analyzer.AnalyzeExhaust;
|
||||
import org.jetbrains.jet.analyzer.AnalyzerFacade;
|
||||
import org.jetbrains.jet.lang.cfg.pseudocode.JetControlFlowDataTraceFactory;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.types.lang.JetStandardLibrary;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.BodiesResolveContext;
|
||||
import org.jetbrains.k2js.analyze.AnalyzerFacadeForJS;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -46,7 +46,16 @@ public enum JSAnalyzerFacadeForIDEA implements AnalyzerFacade {
|
||||
@NotNull Collection<JetFile> files,
|
||||
@NotNull Predicate<PsiFile> filesToAnalyzeCompletely,
|
||||
@NotNull JetControlFlowDataTraceFactory flowDataTraceFactory) {
|
||||
BindingContext context = AnalyzerFacadeForJS.analyzeFiles(files, filesToAnalyzeCompletely, new IDEAConfig(project));
|
||||
return AnalyzeExhaust.success(context, JetStandardLibrary.getInstance());
|
||||
return AnalyzerFacadeForJS.analyzeFiles(files, filesToAnalyzeCompletely, new IDEAConfig(project), true);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public AnalyzeExhaust analyzeBodiesInFiles(@NotNull Project project,
|
||||
@NotNull Predicate<PsiFile> filesForBodiesResolve,
|
||||
@NotNull JetControlFlowDataTraceFactory flowDataTraceFactory,
|
||||
@NotNull BindingTrace traceContext,
|
||||
@NotNull BodiesResolveContext bodiesResolveContext) {
|
||||
return AnalyzerFacadeForJS.analyzeBodiesInFiles(filesForBodiesResolve, new IDEAConfig(project), traceContext, bodiesResolveContext);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//package a {
|
||||
val afoo = abar()
|
||||
val afoo = <error descr="[TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM] Type checking has run into a recursive problem. Easiest workaround: specify types of your declarations explicitly">abar()</error>
|
||||
|
||||
fun abar() = <error descr="[TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM] Type checking has run into a recursive problem. Easiest workaround: specify types of your declarations explicitly">afoo</error>
|
||||
fun abar() = afoo
|
||||
//}
|
||||
|
||||
//package b {
|
||||
|
||||
Reference in New Issue
Block a user