001    /*
002     * Copyright 2010-2015 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.kotlin.js.config;
018    
019    import com.google.common.base.Predicates;
020    import com.intellij.openapi.project.Project;
021    import com.intellij.openapi.util.text.StringUtil;
022    import com.intellij.openapi.vfs.VirtualFile;
023    import com.intellij.psi.PsiFile;
024    import com.intellij.psi.PsiManager;
025    import kotlin.Function1;
026    import kotlin.Unit;
027    import org.jetbrains.annotations.NotNull;
028    import org.jetbrains.annotations.Nullable;
029    import org.jetbrains.kotlin.analyzer.AnalysisResult;
030    import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
031    import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS;
032    import org.jetbrains.kotlin.psi.JetFile;
033    import org.jetbrains.kotlin.psi.JetPsiFactory;
034    import org.jetbrains.kotlin.resolve.BindingContext;
035    import org.jetbrains.kotlin.utils.PathUtil;
036    
037    import java.io.IOException;
038    import java.util.Arrays;
039    import java.util.Collections;
040    import java.util.List;
041    
042    public class LibrarySourcesConfigWithCaching extends LibrarySourcesConfig {
043        public static final List<String> JS_STDLIB =
044                Arrays.asList(PathUtil.getKotlinPathsForDistDirectory().getJsStdLibJarPath().getAbsolutePath());
045    
046        private static List<JetFile> jsLibFiles;
047        private static AnalysisResult result;
048    
049        private BindingContext libraryContext;
050        private ModuleDescriptor libraryModule;
051    
052        private final boolean isUnitTestConfig;
053    
054        public LibrarySourcesConfigWithCaching(
055                @NotNull Project project,
056                @NotNull String moduleId,
057                @NotNull EcmaVersion ecmaVersion,
058                boolean sourcemap,
059                boolean inlineEnabled,
060                boolean isUnitTestConfig
061        ) {
062            super(project, moduleId, JS_STDLIB, ecmaVersion, sourcemap, inlineEnabled);
063            this.isUnitTestConfig = isUnitTestConfig;
064        }
065    
066        @NotNull
067        @Override
068        public List<JetFile> generateLibFiles() {
069            if (jsLibFiles == null) {
070                //noinspection AssignmentToStaticFieldFromInstanceMethod
071                jsLibFiles = super.generateLibFiles();
072            }
073            return jsLibFiles;
074        }
075    
076    
077    
078        @Nullable
079        @Override
080        public ModuleDescriptor getLibraryModule() {
081            if (libraryModule == null) {
082                libraryModule = getResult().getModuleDescriptor();
083            }
084    
085            return libraryModule;
086        }
087    
088        @Nullable
089        @Override
090        public BindingContext getLibraryContext() {
091            if (libraryContext == null) {
092                //TODO check errors?
093                // TopDownAnalyzerFacadeForJS.checkForErrors(allLibFiles, result.getBindingContext());
094                libraryContext = getResult().getBindingContext();
095            }
096    
097            return libraryContext;
098        }
099    
100        @Override
101        public boolean isTestConfig() {
102            return isUnitTestConfig;
103        }
104    
105        @Override
106        protected JetFile getJetFileByVirtualFile(VirtualFile file, String moduleName, PsiManager psiManager) {
107            JetFile jetFile;
108            try {
109                String text = StringUtil.convertLineSeparators(new String(file.contentsToByteArray(false), file.getCharset()));
110                jetFile = new JetPsiFactory(getProject()).createPhysicalFile(file.getName(), text);
111            }
112            catch (IOException e) {
113                JetFile jetFileByVirtualFile = super.getJetFileByVirtualFile(file, moduleName, psiManager);
114                jetFile = new JetPsiFactory(getProject()).createPhysicalFile(file.getPath(), jetFileByVirtualFile.getText());
115            }
116    
117            setupPsiFile(jetFile, moduleName);
118            return jetFile;
119        }
120    
121        private AnalysisResult getResult() {
122            if (result == null) {
123                //noinspection AssignmentToStaticFieldFromInstanceMethod
124                result = TopDownAnalyzerFacadeForJS.analyzeFiles(
125                        generateLibFiles(),
126                        Predicates.<PsiFile>alwaysFalse(),
127                        createConfigWithoutLibFiles(getProject(), getModuleId(), getTarget())
128                );
129            }
130    
131            return result;
132        }
133    
134        @NotNull
135        private static Config createConfigWithoutLibFiles(@NotNull Project project, @NotNull String moduleId, @NotNull EcmaVersion ecmaVersion) {
136            return new Config(project, moduleId, ecmaVersion, /* generate sourcemaps = */ false, /* inlineEnabled = */ false) {
137                @NotNull
138                @Override
139                protected List<JetFile> generateLibFiles() {
140                    return Collections.emptyList();
141                }
142                @Override
143                public boolean checkLibFilesAndReportErrors(@NotNull Function1<String, Unit> report) {
144                    return false;
145                }
146            };
147        }
148    }