001 /*
002 * Copyright 2010-2014 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.google.common.collect.ImmutableList;
022 import com.intellij.openapi.project.Project;
023 import com.intellij.psi.PsiFile;
024 import org.jetbrains.annotations.NotNull;
025 import org.jetbrains.annotations.Nullable;
026 import org.jetbrains.jet.analyzer.AnalyzeExhaust;
027 import org.jetbrains.jet.analyzer.AnalyzerFacadeForEverything;
028 import org.jetbrains.jet.context.ContextPackage;
029 import org.jetbrains.jet.context.GlobalContextImpl;
030 import org.jetbrains.jet.di.InjectorForLazyResolve;
031 import org.jetbrains.jet.di.InjectorForTopDownAnalyzerForJs;
032 import org.jetbrains.jet.lang.PlatformToKotlinClassMap;
033 import org.jetbrains.jet.lang.descriptors.DependencyKind;
034 import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
035 import org.jetbrains.jet.lang.descriptors.ModuleDescriptorImpl;
036 import org.jetbrains.jet.lang.psi.JetFile;
037 import org.jetbrains.jet.lang.resolve.*;
038 import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
039 import org.jetbrains.jet.lang.resolve.lazy.declarations.FileBasedDeclarationProviderFactory;
040 import org.jetbrains.jet.lang.resolve.name.Name;
041 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
042 import org.jetbrains.k2js.config.Config;
043
044 import java.util.Collection;
045 import java.util.Collections;
046 import java.util.List;
047
048 public final class AnalyzerFacadeForJS {
049 public static final List<ImportPath> DEFAULT_IMPORTS = ImmutableList.of(
050 new ImportPath("js.*"),
051 new ImportPath("java.lang.*"),
052 new ImportPath("jet.*"),
053 new ImportPath("kotlin.*"));
054
055 private AnalyzerFacadeForJS() {
056 }
057
058 @NotNull
059 public static BindingContext analyzeFilesAndCheckErrors(@NotNull List<JetFile> files,
060 @NotNull Config config) {
061 BindingContext bindingContext = analyzeFiles(files, Predicates.<PsiFile>alwaysTrue(), config).getBindingContext();
062 checkForErrors(Config.withJsLibAdded(files, config), bindingContext);
063 return bindingContext;
064 }
065
066
067 //NOTE: web demo related method
068 @SuppressWarnings("UnusedDeclaration")
069 @NotNull
070 public static BindingContext analyzeFiles(@NotNull Collection<JetFile> files, @NotNull Config config) {
071 return analyzeFiles(files, Predicates.<PsiFile>alwaysTrue(), config).getBindingContext();
072 }
073
074 @NotNull
075 public static AnalyzeExhaust analyzeFiles(
076 @NotNull Collection<JetFile> files,
077 @NotNull Predicate<PsiFile> filesToAnalyzeCompletely, @NotNull Config config) {
078 return analyzeFiles(files, filesToAnalyzeCompletely, config, false);
079 }
080
081 //TODO: refactor
082 @NotNull
083 public static AnalyzeExhaust analyzeFiles(
084 @NotNull Collection<JetFile> files,
085 @NotNull Predicate<PsiFile> filesToAnalyzeCompletely, @NotNull Config config,
086 boolean storeContextForBodiesResolve) {
087 Project project = config.getProject();
088
089 ModuleDescriptorImpl owner = createJsModule("<module>");
090
091 Predicate<PsiFile> completely = Predicates.and(notLibFiles(config.getLibFiles()), filesToAnalyzeCompletely);
092
093 GlobalContextImpl globalContext = ContextPackage.GlobalContext();
094 TopDownAnalysisParameters topDownAnalysisParameters = new TopDownAnalysisParameters(
095 globalContext.getStorageManager(), globalContext.getExceptionTracker(), completely, false, false, Collections.<AnalyzerScriptParameter>emptyList());
096
097 ModuleDescriptor libraryModule = config.getLibraryModule();
098 if (libraryModule != null) {
099 owner.addFragmentProvider(DependencyKind.BINARIES, libraryModule.getPackageFragmentProvider()); // "import" analyzed library module
100 }
101
102 BindingContext libraryContext = config.getLibraryContext();
103 BindingTrace trace = libraryContext == null
104 ? new BindingTraceContext()
105 : new DelegatingBindingTrace(libraryContext, "trace with preanalyzed library");
106 InjectorForTopDownAnalyzerForJs injector = new InjectorForTopDownAnalyzerForJs(project, topDownAnalysisParameters, trace, owner);
107 try {
108 Collection<JetFile> allFiles = libraryModule != null ?
109 files :
110 Config.withJsLibAdded(files, config);
111 TopDownAnalysisContext topDownAnalysisContext =
112 injector.getTopDownAnalyzer().analyzeFiles(topDownAnalysisParameters, allFiles);
113 BodiesResolveContext bodiesResolveContext = storeContextForBodiesResolve ?
114 new CachedBodiesResolveContext(topDownAnalysisContext) :
115 null;
116 return AnalyzeExhaust.success(trace.getBindingContext(), bodiesResolveContext, owner);
117 }
118 finally {
119 injector.destroy();
120 }
121 }
122
123 @NotNull
124 public static AnalyzeExhaust analyzeBodiesInFiles(
125 @NotNull Predicate<PsiFile> filesToAnalyzeCompletely,
126 @NotNull Config config,
127 @NotNull BindingTrace traceContext,
128 @NotNull BodiesResolveContext bodiesResolveContext,
129 @NotNull ModuleDescriptor module) {
130 Predicate<PsiFile> completely = Predicates.and(notLibFiles(config.getLibFiles()), filesToAnalyzeCompletely);
131
132 return AnalyzerFacadeForEverything.analyzeBodiesInFilesWithJavaIntegration(
133 config.getProject(), Collections.<AnalyzerScriptParameter>emptyList(), completely, traceContext, bodiesResolveContext,
134 module);
135 }
136
137 public static void checkForErrors(@NotNull Collection<JetFile> allFiles, @NotNull BindingContext bindingContext) {
138 AnalyzingUtils.throwExceptionOnErrors(bindingContext);
139 for (JetFile file : allFiles) {
140 AnalyzingUtils.checkForSyntacticErrors(file);
141 }
142 }
143
144 @NotNull
145 private static Predicate<PsiFile> notLibFiles(@NotNull final List<JetFile> jsLibFiles) {
146 return new Predicate<PsiFile>() {
147 @Override
148 public boolean apply(@Nullable PsiFile file) {
149 assert file instanceof JetFile;
150 @SuppressWarnings("UnnecessaryLocalVariable") boolean notLibFile = !jsLibFiles.contains(file);
151 return notLibFile;
152 }
153 };
154 }
155
156 @NotNull
157 public static ResolveSession getLazyResolveSession(Collection<JetFile> files, Config config) {
158 GlobalContextImpl globalContext = ContextPackage.GlobalContext();
159 FileBasedDeclarationProviderFactory declarationProviderFactory = new FileBasedDeclarationProviderFactory(
160 globalContext.getStorageManager(), Config.withJsLibAdded(files, config));
161 ModuleDescriptorImpl module = createJsModule("<lazy module>");
162 module.addFragmentProvider(DependencyKind.BUILT_INS, KotlinBuiltIns.getInstance().getBuiltInsModule().getPackageFragmentProvider());
163
164 return new InjectorForLazyResolve(
165 config.getProject(),
166 globalContext,
167 module,
168 declarationProviderFactory,
169 new BindingTraceContext()).getResolveSession();
170 }
171
172 @NotNull
173 private static ModuleDescriptorImpl createJsModule(@NotNull String name) {
174 return new ModuleDescriptorImpl(Name.special(name), DEFAULT_IMPORTS, PlatformToKotlinClassMap.EMPTY);
175 }
176
177 }