Don't share lazy resolve session between different clients. It can give slice overwrite exceptions.
This commit is contained in:
@@ -68,7 +68,6 @@ public final class AnalyzerFacadeWithCache {
|
|||||||
|
|
||||||
private final static Key<CachedValue<AnalyzeExhaust>> ANALYZE_EXHAUST_HEADERS = Key.create("ANALYZE_EXHAUST_HEADERS");
|
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 final static Key<CachedValue<AnalyzeExhaust>> ANALYZE_EXHAUST_FULL = Key.create("ANALYZE_EXHAUST_FULL");
|
||||||
private final static Key<CachedValue<ResolveSession>> ANALYZE_EXHAUST_LAZY_FULL = Key.create("ANALYZE_EXHAUST_FULL");
|
|
||||||
|
|
||||||
private static final Object lock = new Object();
|
private static final Object lock = new Object();
|
||||||
public static final Function<JetFile, Collection<JetFile>> SINGLE_DECLARATION_PROVIDER = new Function<JetFile, Collection<JetFile>>() {
|
public static final Function<JetFile, Collection<JetFile>> SINGLE_DECLARATION_PROVIDER = new Function<JetFile, Collection<JetFile>>() {
|
||||||
@@ -91,7 +90,7 @@ public final class AnalyzerFacadeWithCache {
|
|||||||
// TODO: Also need to pass several files when user have multi-file environment
|
// TODO: Also need to pass several files when user have multi-file environment
|
||||||
@NotNull
|
@NotNull
|
||||||
public static AnalyzeExhaust analyzeFileWithCache(@NotNull final JetFile file,
|
public static AnalyzeExhaust analyzeFileWithCache(@NotNull final JetFile file,
|
||||||
@NotNull final Function<JetFile, Collection<JetFile>> declarationProvider) {
|
@NotNull final Function<JetFile, Collection<JetFile>> declarationProvider) {
|
||||||
// Need lock for getValue(), because parallel threads can start evaluation of compute() simultaneously
|
// Need lock for getValue(), because parallel threads can start evaluation of compute() simultaneously
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
CachedValue<AnalyzeExhaust> bindingContextCachedValue = file.getUserData(ANALYZE_EXHAUST_FULL);
|
CachedValue<AnalyzeExhaust> bindingContextCachedValue = file.getUserData(ANALYZE_EXHAUST_FULL);
|
||||||
@@ -164,9 +163,9 @@ public final class AnalyzerFacadeWithCache {
|
|||||||
public Result<AnalyzeExhaust> compute() {
|
public Result<AnalyzeExhaust> compute() {
|
||||||
AnalyzeExhaust exhaust = AnalyzerFacadeProvider.getAnalyzerFacadeForFile(fileToCache)
|
AnalyzeExhaust exhaust = AnalyzerFacadeProvider.getAnalyzerFacadeForFile(fileToCache)
|
||||||
.analyzeFiles(fileToCache.getProject(),
|
.analyzeFiles(fileToCache.getProject(),
|
||||||
declarationProvider.fun(fileToCache),
|
declarationProvider.fun(fileToCache),
|
||||||
Collections.<AnalyzerScriptParameter>emptyList(),
|
Collections.<AnalyzerScriptParameter>emptyList(),
|
||||||
Predicates.<PsiFile>alwaysFalse());
|
Predicates.<PsiFile>alwaysFalse());
|
||||||
|
|
||||||
return new Result<AnalyzeExhaust>(exhaust, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
|
return new Result<AnalyzeExhaust>(exhaust, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
|
||||||
}
|
}
|
||||||
@@ -182,82 +181,65 @@ public final class AnalyzerFacadeWithCache {
|
|||||||
LOG.error(e);
|
LOG.error(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Object lazyLock = new Object();
|
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static ResolveSession getLazyResolveSession(@NotNull final JetFile file) {
|
public static ResolveSession getLazyResolveSession(@NotNull final JetFile file) {
|
||||||
synchronized (lazyLock) {
|
final Project fileProject = file.getProject();
|
||||||
final Project fileProject = file.getProject();
|
ModuleDescriptor javaModule = new ModuleDescriptor(Name.special("<java module>"));
|
||||||
CachedValue<ResolveSession> bindingContextCachedValue = file.getUserData(ANALYZE_EXHAUST_LAZY_FULL);
|
|
||||||
if (bindingContextCachedValue == null) {
|
|
||||||
bindingContextCachedValue =
|
|
||||||
CachedValuesManager.getManager(file.getProject()).createCachedValue(new CachedValueProvider<ResolveSession>() {
|
|
||||||
@Override
|
|
||||||
public Result<ResolveSession> compute() {
|
|
||||||
ApplicationUtils.warnTimeConsuming(LOG);
|
|
||||||
|
|
||||||
ModuleDescriptor javaModule = new ModuleDescriptor(Name.special("<java module>"));
|
BindingTraceContext javaResolverTrace = new BindingTraceContext();
|
||||||
|
InjectorForJavaDescriptorResolver injector = new InjectorForJavaDescriptorResolver(
|
||||||
|
fileProject, javaResolverTrace, javaModule, BuiltinsScopeExtensionMode.ALL);
|
||||||
|
|
||||||
InjectorForJavaDescriptorResolver injector = new InjectorForJavaDescriptorResolver(
|
Collection<JetFile> files = JetFilesProvider.getInstance(fileProject).allInScope(GlobalSearchScope.allScope(fileProject));
|
||||||
fileProject, new BindingTraceContext(), javaModule, BuiltinsScopeExtensionMode.ALL);
|
|
||||||
|
|
||||||
Collection<JetFile> files = JetFilesProvider.getInstance(fileProject).allInScope(GlobalSearchScope.allScope(fileProject));
|
// Given file can differ from the original because it can be a virtual copy with some modifications
|
||||||
|
JetFile originalFile = (JetFile) file.getOriginalFile();
|
||||||
|
files.remove(originalFile);
|
||||||
|
files.add(file);
|
||||||
|
|
||||||
// Given file can differ from the original because it can be a virtual copy with some modifications
|
final PsiClassFinder psiClassFinder = injector.getPsiClassFinder();
|
||||||
JetFile originalFile = (JetFile) file.getOriginalFile();
|
|
||||||
files.remove(originalFile);
|
|
||||||
files.add(file);
|
|
||||||
|
|
||||||
final PsiClassFinder psiClassFinder = injector.getPsiClassFinder();
|
// TODO: Replace with stub declaration provider
|
||||||
|
final FileBasedDeclarationProviderFactory declarationProviderFactory = new FileBasedDeclarationProviderFactory(files, new Predicate<FqName>() {
|
||||||
// TODO: Replace with stub declaration provider
|
@Override
|
||||||
final FileBasedDeclarationProviderFactory declarationProviderFactory = new FileBasedDeclarationProviderFactory(files, new Predicate<FqName>() {
|
public boolean apply(FqName fqName) {
|
||||||
@Override
|
return psiClassFinder.findPsiPackage(fqName) != null || new FqName("jet").equals(fqName);
|
||||||
public boolean apply(FqName fqName) {
|
|
||||||
return psiClassFinder.findPsiPackage(fqName) != null || new FqName("jet").equals(fqName);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
final JavaDescriptorResolver javaDescriptorResolver = injector.getJavaDescriptorResolver();
|
|
||||||
|
|
||||||
ModuleConfiguration moduleConfiguration = new ModuleConfiguration() {
|
|
||||||
@Override
|
|
||||||
public void addDefaultImports(@NotNull Collection<JetImportDirective> directives) {
|
|
||||||
final Collection<ImportPath> defaultImports = Lists.newArrayList(JavaBridgeConfiguration.DEFAULT_JAVA_IMPORTS);
|
|
||||||
defaultImports.addAll(Arrays.asList(DefaultModuleConfiguration.DEFAULT_JET_IMPORTS));
|
|
||||||
|
|
||||||
for (ImportPath defaultJetImport : defaultImports) {
|
|
||||||
directives.add(JetPsiFactory.createImportDirective(fileProject, defaultJetImport));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void extendNamespaceScope(
|
|
||||||
@NotNull BindingTrace trace,
|
|
||||||
@NotNull NamespaceDescriptor namespaceDescriptor,
|
|
||||||
@NotNull WritableScope namespaceMemberScope
|
|
||||||
) {
|
|
||||||
FqName fqName = DescriptorUtils.getFQName(namespaceDescriptor).toSafe();
|
|
||||||
if (new FqName("jet").equals(fqName)) {
|
|
||||||
namespaceMemberScope.importScope(JetStandardLibrary.getInstance().getLibraryScope());
|
|
||||||
}
|
|
||||||
if (psiClassFinder.findPsiPackage(fqName) != null) {
|
|
||||||
JavaPackageScope javaPackageScope = javaDescriptorResolver.getJavaPackageScope(fqName, namespaceDescriptor);
|
|
||||||
assert javaPackageScope != null;
|
|
||||||
namespaceMemberScope.importScope(javaPackageScope);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ModuleDescriptor lazyModule = new ModuleDescriptor(Name.special("<lazy module>"));
|
|
||||||
ResolveSession resolveSession = new ResolveSession(fileProject, lazyModule, moduleConfiguration, declarationProviderFactory);
|
|
||||||
|
|
||||||
return new Result<ResolveSession>(resolveSession, PsiModificationTracker.MODIFICATION_COUNT);
|
|
||||||
}
|
|
||||||
}, false);
|
|
||||||
file.putUserData(ANALYZE_EXHAUST_LAZY_FULL, bindingContextCachedValue);
|
|
||||||
}
|
}
|
||||||
return bindingContextCachedValue.getValue();
|
});
|
||||||
}
|
|
||||||
|
final JavaDescriptorResolver javaDescriptorResolver = injector.getJavaDescriptorResolver();
|
||||||
|
|
||||||
|
ModuleConfiguration moduleConfiguration = new ModuleConfiguration() {
|
||||||
|
@Override
|
||||||
|
public void addDefaultImports(@NotNull Collection<JetImportDirective> directives) {
|
||||||
|
final Collection<ImportPath> defaultImports = Lists.newArrayList(JavaBridgeConfiguration.DEFAULT_JAVA_IMPORTS);
|
||||||
|
defaultImports.addAll(Arrays.asList(DefaultModuleConfiguration.DEFAULT_JET_IMPORTS));
|
||||||
|
|
||||||
|
for (ImportPath defaultJetImport : defaultImports) {
|
||||||
|
directives.add(JetPsiFactory.createImportDirective(fileProject, defaultJetImport));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void extendNamespaceScope(
|
||||||
|
@NotNull BindingTrace trace,
|
||||||
|
@NotNull NamespaceDescriptor namespaceDescriptor,
|
||||||
|
@NotNull WritableScope namespaceMemberScope
|
||||||
|
) {
|
||||||
|
FqName fqName = DescriptorUtils.getFQName(namespaceDescriptor).toSafe();
|
||||||
|
if (new FqName("jet").equals(fqName)) {
|
||||||
|
namespaceMemberScope.importScope(JetStandardLibrary.getInstance().getLibraryScope());
|
||||||
|
}
|
||||||
|
if (psiClassFinder.findPsiPackage(fqName) != null) {
|
||||||
|
JavaPackageScope javaPackageScope = javaDescriptorResolver.getJavaPackageScope(fqName, namespaceDescriptor);
|
||||||
|
assert javaPackageScope != null;
|
||||||
|
namespaceMemberScope.importScope(javaPackageScope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ModuleDescriptor lazyModule = new ModuleDescriptor(Name.special("<lazy module>"));
|
||||||
|
|
||||||
|
return new ResolveSession(fileProject, lazyModule, moduleConfiguration, declarationProviderFactory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user