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.context.ContextPackage;
028 import org.jetbrains.jet.context.GlobalContextImpl;
029 import org.jetbrains.jet.di.InjectorForLazyResolve;
030 import org.jetbrains.jet.di.InjectorForTopDownAnalyzerForJs;
031 import org.jetbrains.jet.lang.PlatformToKotlinClassMap;
032 import org.jetbrains.jet.lang.descriptors.DependencyKind;
033 import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
034 import org.jetbrains.jet.lang.descriptors.ModuleDescriptorImpl;
035 import org.jetbrains.jet.lang.psi.JetFile;
036 import org.jetbrains.jet.lang.resolve.*;
037 import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
038 import org.jetbrains.jet.lang.resolve.lazy.declarations.DeclarationProviderFactory;
039 import org.jetbrains.jet.lang.resolve.name.Name;
040 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
041 import org.jetbrains.k2js.config.Config;
042
043 import java.util.Collection;
044 import java.util.List;
045
046 import static org.jetbrains.jet.lang.resolve.lazy.declarations.DeclarationProviderFactoryService.createDeclarationProviderFactory;
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("kotlin.*"),
053 new ImportPath("kotlin.reflect.*")
054 );
055
056 private AnalyzerFacadeForJS() {
057 }
058
059 @NotNull
060 public static BindingContext analyzeFilesAndCheckErrors(@NotNull List<JetFile> files,
061 @NotNull Config config) {
062 BindingContext bindingContext = analyzeFiles(files, Predicates.<PsiFile>alwaysTrue(), config).getBindingContext();
063 checkForErrors(Config.withJsLibAdded(files, config), bindingContext);
064 return bindingContext;
065 }
066
067
068 //NOTE: web demo related method
069 @SuppressWarnings("UnusedDeclaration")
070 @NotNull
071 public static BindingContext analyzeFiles(@NotNull Collection<JetFile> files, @NotNull Config config) {
072 return analyzeFiles(files, Predicates.<PsiFile>alwaysTrue(), config).getBindingContext();
073 }
074
075 //TODO: refactor
076 @NotNull
077 public static AnalyzeExhaust analyzeFiles(
078 @NotNull Collection<JetFile> files,
079 @NotNull Predicate<PsiFile> filesToAnalyzeCompletely,
080 @NotNull Config config
081 ) {
082 Project project = config.getProject();
083
084 ModuleDescriptorImpl owner = createJsModule("<module>");
085
086 Predicate<PsiFile> completely = Predicates.and(notLibFiles(config.getLibFiles()), filesToAnalyzeCompletely);
087
088 GlobalContextImpl globalContext = ContextPackage.GlobalContext();
089 TopDownAnalysisParameters topDownAnalysisParameters = TopDownAnalysisParameters.create(
090 globalContext.getStorageManager(), globalContext.getExceptionTracker(), completely, false, false);
091
092 ModuleDescriptor libraryModule = config.getLibraryModule();
093 if (libraryModule != null) {
094 owner.addFragmentProvider(DependencyKind.BINARIES, libraryModule.getPackageFragmentProvider()); // "import" analyzed library module
095 }
096
097 BindingContext libraryContext = config.getLibraryContext();
098 BindingTrace trace = libraryContext == null
099 ? new BindingTraceContext()
100 : new DelegatingBindingTrace(libraryContext, "trace with preanalyzed library");
101 InjectorForTopDownAnalyzerForJs injector = new InjectorForTopDownAnalyzerForJs(project, topDownAnalysisParameters, trace, owner);
102 try {
103 Collection<JetFile> allFiles = libraryModule != null ?
104 files :
105 Config.withJsLibAdded(files, config);
106 injector.getTopDownAnalyzer().analyzeFiles(topDownAnalysisParameters, allFiles);
107 return AnalyzeExhaust.success(trace.getBindingContext(), owner);
108 }
109 finally {
110 injector.destroy();
111 }
112 }
113
114 public static void checkForErrors(@NotNull Collection<JetFile> allFiles, @NotNull BindingContext bindingContext) {
115 AnalyzingUtils.throwExceptionOnErrors(bindingContext);
116 for (JetFile file : allFiles) {
117 AnalyzingUtils.checkForSyntacticErrors(file);
118 }
119 }
120
121 @NotNull
122 private static Predicate<PsiFile> notLibFiles(@NotNull final List<JetFile> jsLibFiles) {
123 return new Predicate<PsiFile>() {
124 @Override
125 public boolean apply(@Nullable PsiFile file) {
126 assert file instanceof JetFile;
127 @SuppressWarnings("UnnecessaryLocalVariable") boolean notLibFile = !jsLibFiles.contains(file);
128 return notLibFile;
129 }
130 };
131 }
132
133 @NotNull
134 public static ResolveSession getLazyResolveSession(Collection<JetFile> files, Config config) {
135 GlobalContextImpl globalContext = ContextPackage.GlobalContext();
136 DeclarationProviderFactory declarationProviderFactory =
137 createDeclarationProviderFactory(config.getProject(), globalContext.getStorageManager(),
138 Config.withJsLibAdded(files, config));
139 ModuleDescriptorImpl module = createJsModule("<lazy module>");
140 module.addFragmentProvider(DependencyKind.BUILT_INS, KotlinBuiltIns.getInstance().getBuiltInsModule().getPackageFragmentProvider());
141
142 return new InjectorForLazyResolve(
143 config.getProject(),
144 globalContext,
145 module,
146 declarationProviderFactory,
147 new BindingTraceContext()).getResolveSession();
148 }
149
150 @NotNull
151 private static ModuleDescriptorImpl createJsModule(@NotNull String name) {
152 return new ModuleDescriptorImpl(Name.special(name), DEFAULT_IMPORTS, PlatformToKotlinClassMap.EMPTY);
153 }
154
155 }