001/* 002 * Copyright 2010-2012 JetBrains s.r.o. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.jetbrains.k2js.analyze; 018 019import com.google.common.base.Predicate; 020import com.google.common.base.Predicates; 021import com.intellij.openapi.project.Project; 022import com.intellij.psi.PsiFile; 023import org.jetbrains.annotations.NotNull; 024import org.jetbrains.annotations.Nullable; 025import org.jetbrains.jet.analyzer.AnalyzeExhaust; 026import org.jetbrains.jet.analyzer.AnalyzerFacadeForEverything; 027import org.jetbrains.jet.di.InjectorForTopDownAnalyzerForJs; 028import org.jetbrains.jet.lang.PlatformToKotlinClassMap; 029import org.jetbrains.jet.lang.descriptors.ModuleDescriptor; 030import org.jetbrains.jet.lang.descriptors.ModuleDescriptorImpl; 031import org.jetbrains.jet.lang.psi.JetFile; 032import org.jetbrains.jet.lang.resolve.*; 033import org.jetbrains.jet.lang.resolve.lazy.ResolveSession; 034import org.jetbrains.jet.lang.resolve.lazy.declarations.FileBasedDeclarationProviderFactory; 035import org.jetbrains.jet.lang.resolve.lazy.storage.LockBasedStorageManager; 036import org.jetbrains.jet.lang.resolve.name.FqName; 037import org.jetbrains.jet.lang.resolve.name.Name; 038import org.jetbrains.k2js.config.Config; 039 040import java.util.Collection; 041import java.util.Collections; 042import java.util.List; 043 044public final class AnalyzerFacadeForJS { 045 046 private AnalyzerFacadeForJS() { 047 } 048 049 @NotNull 050 public static BindingContext analyzeFilesAndCheckErrors(@NotNull List<JetFile> files, 051 @NotNull Config config) { 052 BindingContext bindingContext = analyzeFiles(files, Predicates.<PsiFile>alwaysTrue(), config).getBindingContext(); 053 checkForErrors(Config.withJsLibAdded(files, config), bindingContext); 054 return bindingContext; 055 } 056 057 058 //NOTE: web demo related method 059 @SuppressWarnings("UnusedDeclaration") 060 @NotNull 061 public static BindingContext analyzeFiles(@NotNull Collection<JetFile> files, @NotNull Config config) { 062 return analyzeFiles(files, Predicates.<PsiFile>alwaysTrue(), config).getBindingContext(); 063 } 064 065 @NotNull 066 public static AnalyzeExhaust analyzeFiles( 067 @NotNull Collection<JetFile> files, 068 @NotNull Predicate<PsiFile> filesToAnalyzeCompletely, @NotNull Config config) { 069 return analyzeFiles(files, filesToAnalyzeCompletely, config, false); 070 } 071 072 //TODO: refactor 073 @NotNull 074 public static AnalyzeExhaust analyzeFiles( 075 @NotNull Collection<JetFile> files, 076 @NotNull Predicate<PsiFile> filesToAnalyzeCompletely, @NotNull Config config, 077 boolean storeContextForBodiesResolve) { 078 Project project = config.getProject(); 079 080 ModuleDescriptorImpl owner = createJsModule("<module>"); 081 082 Predicate<PsiFile> completely = Predicates.and(notLibFiles(config.getLibFiles()), filesToAnalyzeCompletely); 083 084 TopDownAnalysisParameters topDownAnalysisParameters = new TopDownAnalysisParameters( 085 completely, false, false, Collections.<AnalyzerScriptParameter>emptyList()); 086 087 BindingContext libraryBindingContext = config.getLibraryBindingContext(); 088 BindingTrace trace = libraryBindingContext == null ? 089 new ObservableBindingTrace(new BindingTraceContext()) : 090 new DelegatingBindingTrace(libraryBindingContext, "trace for analyzing library in js"); 091 owner.setModuleConfiguration(new JsConfiguration(libraryBindingContext)); 092 InjectorForTopDownAnalyzerForJs injector = new InjectorForTopDownAnalyzerForJs(project, topDownAnalysisParameters, trace, owner); 093 try { 094 Collection<JetFile> allFiles = libraryBindingContext != null ? 095 files : 096 Config.withJsLibAdded(files, config); 097 injector.getTopDownAnalyzer().analyzeFiles(allFiles, Collections.<AnalyzerScriptParameter>emptyList()); 098 BodiesResolveContext bodiesResolveContext = storeContextForBodiesResolve ? 099 new CachedBodiesResolveContext(injector.getTopDownAnalysisContext()) : 100 null; 101 return AnalyzeExhaust.success(trace.getBindingContext(), bodiesResolveContext, owner); 102 } 103 finally { 104 injector.destroy(); 105 } 106 } 107 108 @NotNull 109 public static AnalyzeExhaust analyzeBodiesInFiles( 110 @NotNull Predicate<PsiFile> filesToAnalyzeCompletely, 111 @NotNull Config config, 112 @NotNull BindingTrace traceContext, 113 @NotNull BodiesResolveContext bodiesResolveContext, 114 @NotNull ModuleDescriptor module) { 115 Predicate<PsiFile> completely = Predicates.and(notLibFiles(config.getLibFiles()), filesToAnalyzeCompletely); 116 117 return AnalyzerFacadeForEverything.analyzeBodiesInFilesWithJavaIntegration( 118 config.getProject(), Collections.<AnalyzerScriptParameter>emptyList(), completely, traceContext, bodiesResolveContext, 119 module); 120 } 121 122 public static void checkForErrors(@NotNull Collection<JetFile> allFiles, @NotNull BindingContext bindingContext) { 123 AnalyzingUtils.throwExceptionOnErrors(bindingContext); 124 for (JetFile file : allFiles) { 125 AnalyzingUtils.checkForSyntacticErrors(file); 126 } 127 } 128 129 @NotNull 130 private static Predicate<PsiFile> notLibFiles(@NotNull final List<JetFile> jsLibFiles) { 131 return new Predicate<PsiFile>() { 132 @Override 133 public boolean apply(@Nullable PsiFile file) { 134 assert file instanceof JetFile; 135 @SuppressWarnings("UnnecessaryLocalVariable") boolean notLibFile = !jsLibFiles.contains(file); 136 return notLibFile; 137 } 138 }; 139 } 140 141 @NotNull 142 public static ResolveSession getLazyResolveSession(Collection<JetFile> files, Config config) { 143 LockBasedStorageManager storageManager = new LockBasedStorageManager(); 144 FileBasedDeclarationProviderFactory declarationProviderFactory = new FileBasedDeclarationProviderFactory( 145 storageManager, Config.withJsLibAdded(files, config), Predicates.<FqName>alwaysFalse()); 146 ModuleDescriptorImpl lazyModule = createJsModule("<lazy module>"); 147 lazyModule.setModuleConfiguration(new JsConfiguration(null)); 148 return new ResolveSession(config.getProject(), storageManager, lazyModule, declarationProviderFactory); 149 } 150 151 @NotNull 152 private static ModuleDescriptorImpl createJsModule(@NotNull String name) { 153 return new ModuleDescriptorImpl(Name.special(name), JsConfiguration.DEFAULT_IMPORT_PATHS, PlatformToKotlinClassMap.EMPTY); 154 } 155 156}