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.InjectorForTopDownAnalyzerForJs;
030 import org.jetbrains.jet.lang.PlatformToKotlinClassMap;
031 import org.jetbrains.jet.lang.descriptors.ModuleDescriptor;
032 import org.jetbrains.jet.lang.descriptors.impl.ModuleDescriptorImpl;
033 import org.jetbrains.jet.lang.psi.JetFile;
034 import org.jetbrains.jet.lang.resolve.*;
035 import org.jetbrains.jet.lang.resolve.name.Name;
036 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
037 import org.jetbrains.k2js.config.Config;
038
039 import java.util.Collection;
040 import java.util.List;
041
042 public final class TopDownAnalyzerFacadeForJS {
043 public static final List<ImportPath> DEFAULT_IMPORTS = ImmutableList.of(
044 new ImportPath("java.lang.*"),
045 new ImportPath("kotlin.*"),
046 new ImportPath("kotlin.js.*")
047 );
048
049 private TopDownAnalyzerFacadeForJS() {
050 }
051
052 //NOTE: web demo related method
053 @SuppressWarnings("UnusedDeclaration")
054 @NotNull
055 public static BindingContext analyzeFiles(@NotNull Collection<JetFile> files, @NotNull Config config) {
056 return analyzeFiles(files, Predicates.<PsiFile>alwaysTrue(), config).getBindingContext();
057 }
058
059 //TODO: refactor
060 @NotNull
061 public static AnalyzeExhaust analyzeFiles(
062 @NotNull Collection<JetFile> files,
063 @NotNull Predicate<PsiFile> filesToAnalyzeCompletely,
064 @NotNull Config config
065 ) {
066 Project project = config.getProject();
067
068 ModuleDescriptorImpl owner = createJsModule("<module>");
069
070 Predicate<PsiFile> completely = Predicates.and(notLibFiles(config.getLibFiles()), filesToAnalyzeCompletely);
071
072 GlobalContextImpl globalContext = ContextPackage.GlobalContext();
073 TopDownAnalysisParameters topDownAnalysisParameters = TopDownAnalysisParameters.create(
074 globalContext.getStorageManager(), globalContext.getExceptionTracker(), completely, false, false);
075
076 owner.addDependencyOnModule(owner);
077 owner.addDependencyOnModule(KotlinBuiltIns.getInstance().getBuiltInsModule());
078 ModuleDescriptor libraryModule = config.getLibraryModule();
079 if (libraryModule != null) {
080 owner.addDependencyOnModule((ModuleDescriptorImpl) libraryModule); // "import" analyzed library module
081 }
082 owner.seal();
083
084 BindingContext libraryContext = config.getLibraryContext();
085 BindingTrace trace = libraryContext == null
086 ? new BindingTraceContext()
087 : new DelegatingBindingTrace(libraryContext, "trace with preanalyzed library");
088 InjectorForTopDownAnalyzerForJs injector = new InjectorForTopDownAnalyzerForJs(project, topDownAnalysisParameters, trace, owner);
089 try {
090 Collection<JetFile> allFiles = libraryModule != null ?
091 files :
092 Config.withJsLibAdded(files, config);
093 injector.getTopDownAnalyzer().analyzeFiles(topDownAnalysisParameters, allFiles);
094 return AnalyzeExhaust.success(trace.getBindingContext(), owner);
095 }
096 finally {
097 injector.destroy();
098 }
099 }
100
101 public static void checkForErrors(@NotNull Collection<JetFile> allFiles, @NotNull BindingContext bindingContext) {
102 AnalyzingUtils.throwExceptionOnErrors(bindingContext);
103 for (JetFile file : allFiles) {
104 AnalyzingUtils.checkForSyntacticErrors(file);
105 }
106 }
107
108 @NotNull
109 private static Predicate<PsiFile> notLibFiles(@NotNull final List<JetFile> jsLibFiles) {
110 return new Predicate<PsiFile>() {
111 @Override
112 public boolean apply(@Nullable PsiFile file) {
113 assert file instanceof JetFile;
114 @SuppressWarnings("UnnecessaryLocalVariable") boolean notLibFile = !jsLibFiles.contains(file);
115 return notLibFile;
116 }
117 };
118 }
119
120 @NotNull
121 private static ModuleDescriptorImpl createJsModule(@NotNull String name) {
122 return new ModuleDescriptorImpl(Name.special(name), DEFAULT_IMPORTS, PlatformToKotlinClassMap.EMPTY);
123 }
124
125 }