From 5fe4e2f4aec9ba6f18cb621edf77c12e05ea770e Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Thu, 7 Mar 2013 13:09:35 +0400 Subject: [PATCH] Introduce js header library concept --- idea/src/META-INF/plugin.xml | 3 +- .../CachingLibraryPresentationProvider.java | 50 ++++++++ .../framework/JSFrameworkSupportProvider.java | 2 +- ...tion.java => JSLibraryStdDescription.java} | 6 +- ... => JSLibraryStdPresentationProvider.java} | 11 +- .../JavaFrameworkSupportProvider.java | 2 +- .../JavaRuntimePresentationProvider.java | 2 +- .../JsHeaderLibraryPresentationProvider.java | 76 +++++++++++++ .../framework/KotlinFrameworkDetector.java | 107 ++++++++---------- 9 files changed, 190 insertions(+), 69 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/plugin/framework/CachingLibraryPresentationProvider.java rename idea/src/org/jetbrains/jet/plugin/framework/{JSLibraryDescription.java => JSLibraryStdDescription.java} (96%) rename idea/src/org/jetbrains/jet/plugin/framework/{JSHeadersPresentationProvider.java => JSLibraryStdPresentationProvider.java} (78%) create mode 100644 idea/src/org/jetbrains/jet/plugin/framework/JsHeaderLibraryPresentationProvider.java diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 6928df8961b..61cd3de7e53 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -222,7 +222,8 @@ - + + diff --git a/idea/src/org/jetbrains/jet/plugin/framework/CachingLibraryPresentationProvider.java b/idea/src/org/jetbrains/jet/plugin/framework/CachingLibraryPresentationProvider.java new file mode 100644 index 00000000000..7b657729645 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/framework/CachingLibraryPresentationProvider.java @@ -0,0 +1,50 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.framework; + +import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.libraries.*; +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; +import java.util.List; + +public abstract class CachingLibraryPresentationProvider extends LibraryPresentationProvider { + protected CachingLibraryPresentationProvider(@NotNull LibraryKind kind) { + super(kind); + } + + public boolean isDetected(@NotNull Library library) { + return isDetected(Arrays.asList(library.getFiles(OrderRootType.CLASSES))); + } + + public boolean isDetected(@NotNull List classesRoots) { + return cachedDetect(classesRoots, getKind()); + } + + private static boolean cachedDetect(@NotNull List classesRoots, @NotNull final LibraryKind libraryKind) { + return !LibraryDetectionManager.getInstance().processProperties( + classesRoots, + new LibraryDetectionManager.LibraryPropertiesProcessor() { + @Override + public

boolean processProperties(@NotNull LibraryKind processedKind, @NotNull P properties) { + return !libraryKind.equals(processedKind); + } + }); + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/framework/JSFrameworkSupportProvider.java b/idea/src/org/jetbrains/jet/plugin/framework/JSFrameworkSupportProvider.java index 61db4a55295..ac0ee3960cf 100644 --- a/idea/src/org/jetbrains/jet/plugin/framework/JSFrameworkSupportProvider.java +++ b/idea/src/org/jetbrains/jet/plugin/framework/JSFrameworkSupportProvider.java @@ -45,7 +45,7 @@ public class JSFrameworkSupportProvider extends FrameworkSupportInModuleProvider @Nullable @Override public CustomLibraryDescription createLibraryDescription() { - return new JSLibraryDescription(); + return new JSLibraryStdDescription(); } @Nullable diff --git a/idea/src/org/jetbrains/jet/plugin/framework/JSLibraryDescription.java b/idea/src/org/jetbrains/jet/plugin/framework/JSLibraryStdDescription.java similarity index 96% rename from idea/src/org/jetbrains/jet/plugin/framework/JSLibraryDescription.java rename to idea/src/org/jetbrains/jet/plugin/framework/JSLibraryStdDescription.java index 3fd75fd0ec0..75a6bd946f6 100644 --- a/idea/src/org/jetbrains/jet/plugin/framework/JSLibraryDescription.java +++ b/idea/src/org/jetbrains/jet/plugin/framework/JSLibraryStdDescription.java @@ -35,9 +35,11 @@ import org.jetbrains.jet.utils.PathUtil; import javax.swing.*; import java.io.File; -import java.util.*; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; -public class JSLibraryDescription extends CustomLibraryDescription { +public class JSLibraryStdDescription extends CustomLibraryDescription { public static final LibraryKind KOTLIN_JAVASCRIPT_KIND = LibraryKind.create("kotlin-js-stdlib"); public static final String LIBRARY_NAME = "KotlinJavaScript"; diff --git a/idea/src/org/jetbrains/jet/plugin/framework/JSHeadersPresentationProvider.java b/idea/src/org/jetbrains/jet/plugin/framework/JSLibraryStdPresentationProvider.java similarity index 78% rename from idea/src/org/jetbrains/jet/plugin/framework/JSHeadersPresentationProvider.java rename to idea/src/org/jetbrains/jet/plugin/framework/JSLibraryStdPresentationProvider.java index 857791169a2..8c32a8273d8 100644 --- a/idea/src/org/jetbrains/jet/plugin/framework/JSHeadersPresentationProvider.java +++ b/idea/src/org/jetbrains/jet/plugin/framework/JSLibraryStdPresentationProvider.java @@ -28,13 +28,13 @@ import org.jetbrains.jet.utils.PathUtil; import javax.swing.*; import java.util.List; -public class JSHeadersPresentationProvider extends LibraryPresentationProvider { - public static JSHeadersPresentationProvider getInstance() { - return LibraryPresentationProvider.EP_NAME.findExtension(JSHeadersPresentationProvider.class); +public class JSLibraryStdPresentationProvider extends CachingLibraryPresentationProvider { + public static JSLibraryStdPresentationProvider getInstance() { + return LibraryPresentationProvider.EP_NAME.findExtension(JSLibraryStdPresentationProvider.class); } - protected JSHeadersPresentationProvider() { - super(JSLibraryDescription.KOTLIN_JAVASCRIPT_KIND); + protected JSLibraryStdPresentationProvider() { + super(JSLibraryStdDescription.KOTLIN_JAVASCRIPT_KIND); } @Nullable @@ -53,6 +53,7 @@ public class JSHeadersPresentationProvider extends LibraryPresentationProvider { +public class JavaRuntimePresentationProvider extends CachingLibraryPresentationProvider { public static JavaRuntimePresentationProvider getInstance() { return LibraryPresentationProvider.EP_NAME.findExtension(JavaRuntimePresentationProvider.class); } diff --git a/idea/src/org/jetbrains/jet/plugin/framework/JsHeaderLibraryPresentationProvider.java b/idea/src/org/jetbrains/jet/plugin/framework/JsHeaderLibraryPresentationProvider.java new file mode 100644 index 00000000000..43766550229 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/framework/JsHeaderLibraryPresentationProvider.java @@ -0,0 +1,76 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.framework; + +import com.intellij.framework.library.LibraryVersionProperties; +import com.intellij.openapi.roots.libraries.LibraryKind; +import com.intellij.openapi.roots.libraries.LibraryPresentationProvider; +import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.CommonProcessors; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.plugin.JetFileType; +import org.jetbrains.jet.plugin.JetIcons; + +import javax.swing.*; +import java.util.List; + +public class JsHeaderLibraryPresentationProvider extends CachingLibraryPresentationProvider { + public static final LibraryKind KOTLIN_JAVASCRIPT_HEADER_KIND = LibraryKind.create("kotlin-js-header"); + + public static JsHeaderLibraryPresentationProvider getInstance() { + return LibraryPresentationProvider.EP_NAME.findExtension(JsHeaderLibraryPresentationProvider.class); + } + + protected JsHeaderLibraryPresentationProvider() { + super(KOTLIN_JAVASCRIPT_HEADER_KIND); + } + + @Nullable + @Override + public Icon getIcon() { + return JetIcons.SMALL_LOGO_13; + } + + @Nullable + @Override + public LibraryVersionProperties detect(@NotNull List classesRoots) { + if (JavaRuntimePresentationProvider.getInstance().detect(classesRoots) != null) { + // Prevent clashing with java runtime + return null; + } + + for (VirtualFile file : classesRoots) { + CommonProcessors.FindFirstProcessor findKTProcessor = new CommonProcessors.FindFirstProcessor() { + @Override + protected boolean accept(VirtualFile file) { + String extension = file.getExtension(); + return extension != null && extension.equals(JetFileType.INSTANCE.getDefaultExtension()); + } + }; + + VfsUtil.processFilesRecursively(file, findKTProcessor); + + if (findKTProcessor.isFound()) { + return new LibraryVersionProperties(null); + } + } + + return null; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/framework/KotlinFrameworkDetector.java b/idea/src/org/jetbrains/jet/plugin/framework/KotlinFrameworkDetector.java index 19e9bd19e30..edbab372b50 100644 --- a/idea/src/org/jetbrains/jet/plugin/framework/KotlinFrameworkDetector.java +++ b/idea/src/org/jetbrains/jet/plugin/framework/KotlinFrameworkDetector.java @@ -17,6 +17,7 @@ package org.jetbrains.jet.plugin.framework; import com.google.common.collect.Lists; +import com.google.common.collect.Sets; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; @@ -26,25 +27,25 @@ import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.ProjectRootModificationTracker; import com.intellij.openapi.roots.libraries.Library; -import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Key; import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.Ref; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.CachedValue; import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; +import com.intellij.util.PathUtil; import com.intellij.util.Processor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.plugin.versions.KotlinRuntimeLibraryUtil; -import org.jetbrains.jet.utils.PathUtil; import org.jetbrains.k2js.config.EcmaVersion; import java.util.Arrays; -import java.util.Collection; import java.util.List; +import java.util.Set; public class KotlinFrameworkDetector { private static final Key> IS_KOTLIN_JS_MODULE = Key.create("IS_KOTLIN_JS_MODULE"); @@ -83,8 +84,7 @@ public class KotlinFrameworkDetector { result = CachedValuesManager.getManager(module.getProject()).createCachedValue(new CachedValueProvider() { @Override public Result compute() { - return Result.create(getStandardJavaScriptLibrary(module) != null, - ProjectRootModificationTracker.getInstance(module.getProject())); + return Result.create(getJSStandardLibrary(module) != null, ProjectRootModificationTracker.getInstance(module.getProject())); } }, false); @@ -94,47 +94,6 @@ public class KotlinFrameworkDetector { return result.getValue(); } - @NotNull - private static Collection getJavaScriptHeadersLibraries(final Module module) { - final Collection headersLibraries = Lists.newArrayList(); - - ApplicationManager.getApplication().runReadAction(new Runnable() { - @Override - public void run() { - ModuleRootManager.getInstance(module).orderEntries().librariesOnly().forEachLibrary(new Processor() { - @Override - public boolean process(Library library) { - if (JSHeadersPresentationProvider.getInstance().detect( - Arrays.asList(library.getFiles(OrderRootType.CLASSES))) != null) { - headersLibraries.add(library); - } - - return true; - } - }); - } - }); - - return headersLibraries; - } - - @Nullable - private static Library getStandardJavaScriptLibrary(final Module module) { - return ApplicationManager.getApplication().runReadAction(new Computable() { - @Override - public Library compute() { - for (Library library : getJavaScriptHeadersLibraries(module)) { - for (VirtualFile file : library.getFiles(OrderRootType.SOURCES)) { - if (file.getName().equals(PathUtil.JS_LIB_JAR_NAME)) { - return library; - } - } - } - return null; - } - }); - } - @NotNull public static Pair, String> getLibLocationAndTargetForProject(@NotNull Project project) { Module[] modules = ModuleManager.getInstance(project).getModules(); @@ -147,20 +106,52 @@ public class KotlinFrameworkDetector { return Pair.empty(); } - public static Pair, String> getLibLocationAndTargetForProject(Module module) { - Library library = getStandardJavaScriptLibrary(module); + public static Pair, String> getLibLocationAndTargetForProject(final Module module) { + final Set pathsToJSLib = Sets.newHashSet(); - if (library != null) { - List pathsToJSLib = Lists.newArrayList(); - VirtualFile[] files = library.getRootProvider().getFiles(OrderRootType.SOURCES); - for (VirtualFile file : files) { - pathsToJSLib.add(com.intellij.util.PathUtil.getLocalPath(file)); + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + ModuleRootManager.getInstance(module).orderEntries().librariesOnly().forEachLibrary(new Processor() { + @Override + public boolean process(Library library) { + if (JsHeaderLibraryPresentationProvider.getInstance().isDetected(library)) { + for (VirtualFile file : library.getRootProvider().getFiles(OrderRootType.SOURCES)) { + pathsToJSLib.add(PathUtil.getLocalPath(file)); + } + } + + return true; + } + }); } + }); - return Pair.create(pathsToJSLib, EcmaVersion.defaultVersion().toString()); - } - else { - throw new IllegalStateException("Should be called for JS module only. JS library is expected to be found"); - } + return Pair., String>create(Lists.newArrayList(pathsToJSLib), EcmaVersion.defaultVersion().toString()); + } + + + @Nullable + private static Library getJSStandardLibrary(final Module module) { + final Ref jsLibrary = Ref.create(); + + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + ModuleRootManager.getInstance(module).orderEntries().librariesOnly().forEachLibrary(new Processor() { + @Override + public boolean process(Library library) { + if (JSLibraryStdPresentationProvider.getInstance().detect(Arrays.asList(library.getFiles(OrderRootType.CLASSES))) != null) { + jsLibrary.set(library); + return false; + } + + return true; + } + }); + } + }); + + return jsLibrary.get(); } }