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.jet.lang.resolve.java;
018    
019    import com.google.common.base.Predicate;
020    import com.google.common.collect.ImmutableList;
021    import com.intellij.openapi.project.Project;
022    import com.intellij.openapi.vfs.VirtualFile;
023    import com.intellij.psi.PsiFile;
024    import com.intellij.psi.search.GlobalSearchScope;
025    import kotlin.Function1;
026    import kotlin.KotlinPackage;
027    import org.jetbrains.annotations.NotNull;
028    import org.jetbrains.jet.analyzer.AnalyzeExhaust;
029    import org.jetbrains.jet.analyzer.AnalyzerFacade;
030    import org.jetbrains.jet.context.ContextPackage;
031    import org.jetbrains.jet.context.GlobalContext;
032    import org.jetbrains.jet.context.GlobalContextImpl;
033    import org.jetbrains.jet.di.InjectorForLazyResolveWithJava;
034    import org.jetbrains.jet.di.InjectorForTopDownAnalyzerForJvm;
035    import org.jetbrains.jet.lang.descriptors.DependencyKind;
036    import org.jetbrains.jet.lang.descriptors.impl.ModuleDescriptorImpl;
037    import org.jetbrains.jet.lang.psi.JetFile;
038    import org.jetbrains.jet.lang.resolve.BindingTrace;
039    import org.jetbrains.jet.lang.resolve.BindingTraceContext;
040    import org.jetbrains.jet.lang.resolve.ImportPath;
041    import org.jetbrains.jet.lang.resolve.TopDownAnalysisParameters;
042    import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap;
043    import org.jetbrains.jet.lang.resolve.kotlin.incremental.IncrementalCache;
044    import org.jetbrains.jet.lang.resolve.kotlin.incremental.IncrementalCacheProvider;
045    import org.jetbrains.jet.lang.resolve.kotlin.incremental.IncrementalPackageFragmentProvider;
046    import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
047    import org.jetbrains.jet.lang.resolve.lazy.declarations.DeclarationProviderFactory;
048    import org.jetbrains.jet.lang.resolve.lazy.declarations.DeclarationProviderFactoryService;
049    import org.jetbrains.jet.lang.resolve.name.Name;
050    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
051    
052    import java.io.File;
053    import java.util.Collection;
054    import java.util.Collections;
055    import java.util.List;
056    
057    public enum AnalyzerFacadeForJVM implements AnalyzerFacade {
058    
059        INSTANCE;
060    
061        public static final List<ImportPath> DEFAULT_IMPORTS = ImmutableList.of(
062                new ImportPath("java.lang.*"),
063                new ImportPath("kotlin.*"),
064                new ImportPath("kotlin.jvm.*"),
065                new ImportPath("kotlin.io.*")
066        );
067    
068        public static class JvmSetup extends BasicSetup {
069    
070            private final JavaDescriptorResolver javaDescriptorResolver;
071    
072            public JvmSetup(@NotNull ResolveSession session, @NotNull JavaDescriptorResolver javaDescriptorResolver) {
073                super(session);
074                this.javaDescriptorResolver = javaDescriptorResolver;
075            }
076    
077            @NotNull
078            public JavaDescriptorResolver getJavaDescriptorResolver() {
079                return javaDescriptorResolver;
080            }
081        }
082    
083        private AnalyzerFacadeForJVM() {
084        }
085    
086        @NotNull
087        @Override
088        public JvmSetup createSetup(
089                @NotNull Project fileProject,
090                @NotNull Collection<JetFile> syntheticFiles,
091                @NotNull GlobalSearchScope filesScope
092        ) {
093            return createSetup(fileProject, syntheticFiles, filesScope, new BindingTraceContext(), true);
094        }
095    
096        @NotNull
097        public static ResolveSession createLazyResolveSession(
098                @NotNull Project project,
099                @NotNull Collection<JetFile> files,
100                @NotNull BindingTrace trace,
101                boolean addBuiltIns
102        ) {
103            List<VirtualFile> virtualFiles = KotlinPackage.map(files, new Function1<JetFile, VirtualFile>() {
104                @Override
105                public VirtualFile invoke(JetFile file) {
106                    return file.getVirtualFile();
107                }
108            });
109            return createSetup(project, Collections.<JetFile>emptyList(),
110                               GlobalSearchScope.filesScope(project, virtualFiles), trace, addBuiltIns).getLazyResolveSession();
111        }
112    
113        public static JvmSetup createSetup(
114                @NotNull Project project,
115                @NotNull Collection<JetFile> syntheticFiles,
116                @NotNull GlobalSearchScope filesScope,
117                @NotNull BindingTrace trace,
118                boolean addBuiltIns
119        ) {
120            GlobalContextImpl globalContext = ContextPackage.GlobalContext();
121    
122            DeclarationProviderFactory declarationProviderFactory = DeclarationProviderFactoryService.OBJECT$
123                    .createDeclarationProviderFactory(project, globalContext.getStorageManager(), syntheticFiles, filesScope);
124    
125            InjectorForLazyResolveWithJava resolveWithJava = new InjectorForLazyResolveWithJava(
126                    project,
127                    globalContext,
128                    declarationProviderFactory,
129                    trace);
130    
131            resolveWithJava.getModule().addFragmentProvider(
132                    DependencyKind.BINARIES, resolveWithJava.getJavaDescriptorResolver().getPackageFragmentProvider());
133    
134            if (addBuiltIns) {
135                resolveWithJava.getModule().addFragmentProvider(
136                        DependencyKind.BUILT_INS,
137                        KotlinBuiltIns.getInstance().getBuiltInsModule().getPackageFragmentProvider());
138            }
139            return new JvmSetup(resolveWithJava.getResolveSession(), resolveWithJava.getJavaDescriptorResolver());
140        }
141    
142        @NotNull
143        public static AnalyzeExhaust analyzeFilesWithJavaIntegration(
144                Project project,
145                Collection<JetFile> files,
146                BindingTrace trace,
147                Predicate<PsiFile> filesToAnalyzeCompletely,
148                ModuleDescriptorImpl module,
149                List<String> moduleIds,
150                IncrementalCache incrementalCache
151        ) {
152            GlobalContext globalContext = ContextPackage.GlobalContext();
153            TopDownAnalysisParameters topDownAnalysisParameters = TopDownAnalysisParameters.create(
154                    globalContext.getStorageManager(),
155                    globalContext.getExceptionTracker(),
156                    filesToAnalyzeCompletely,
157                    false,
158                    false
159            );
160    
161            InjectorForTopDownAnalyzerForJvm injector = new InjectorForTopDownAnalyzerForJvm(project, topDownAnalysisParameters, trace, module);
162            try {
163                module.addFragmentProvider(DependencyKind.BINARIES, injector.getJavaDescriptorResolver().getPackageFragmentProvider());
164    
165                if (incrementalCache != null && moduleIds != null) {
166                    for (String moduleId : moduleIds) {
167                        module.addFragmentProvider(
168                                DependencyKind.SOURCES,
169                                new IncrementalPackageFragmentProvider(
170                                        files, module, globalContext.getStorageManager(), injector.getDeserializationGlobalContextForJava(),
171                                        incrementalCache, moduleId, injector.getJavaDescriptorResolver()
172                                )
173                        );
174                    }
175                }
176    
177                injector.getTopDownAnalyzer().analyzeFiles(topDownAnalysisParameters, files);
178                return AnalyzeExhaust.success(trace.getBindingContext(), module);
179            }
180            finally {
181                injector.destroy();
182            }
183        }
184    
185        @NotNull
186        public static ModuleDescriptorImpl createJavaModule(@NotNull String name) {
187            return new ModuleDescriptorImpl(Name.special(name), DEFAULT_IMPORTS, JavaToKotlinClassMap.getInstance());
188        }
189    }