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
017 package org.jetbrains.k2js.analyze;
018
019 import com.google.common.base.Predicate;
020 import com.google.common.base.Predicates;
021 import com.intellij.openapi.project.Project;
022 import com.intellij.psi.PsiFile;
023 import org.jetbrains.annotations.NotNull;
024 import org.jetbrains.annotations.Nullable;
025 import org.jetbrains.jet.analyzer.AnalyzeExhaust;
026 import org.jetbrains.jet.analyzer.AnalyzerFacadeForEverything;
027 import org.jetbrains.jet.di.InjectorForTopDownAnalyzerForJs;
028 import org.jetbrains.jet.lang.PlatformToKotlinClassMap;
029 import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
030 import org.jetbrains.jet.lang.descriptors.ModuleDescriptorImpl;
031 import org.jetbrains.jet.lang.psi.JetFile;
032 import org.jetbrains.jet.lang.resolve.*;
033 import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
034 import org.jetbrains.jet.lang.resolve.lazy.declarations.FileBasedDeclarationProviderFactory;
035 import org.jetbrains.jet.lang.resolve.lazy.storage.LockBasedStorageManager;
036 import org.jetbrains.jet.lang.resolve.name.FqName;
037 import org.jetbrains.jet.lang.resolve.name.Name;
038 import org.jetbrains.k2js.config.Config;
039
040 import java.util.Collection;
041 import java.util.Collections;
042 import java.util.List;
043
044 public 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 }