diff --git a/.idea/modules.xml b/.idea/modules.xml index 78bc57a69b28..856f894213d6 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -430,6 +430,8 @@ + + diff --git a/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/ExternalProjectSettings.java b/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/ExternalProjectSettings.java index d8926c31ed90..2156b25ea2a3 100644 --- a/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/ExternalProjectSettings.java +++ b/platform/external-system-api/src/com/intellij/openapi/externalSystem/settings/ExternalProjectSettings.java @@ -15,6 +15,7 @@ */ package com.intellij.openapi.externalSystem.settings; +import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.openapi.util.Comparing; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -45,7 +46,7 @@ public abstract class ExternalProjectSettings implements Comparable 0) { - jvmAgentSetup = DEBUG_SETUP_PREFIX + myDebugPort; - if (getForkSocket() != null) { - jvmAgentSetup += " -forkSocket" + getForkSocket().getLocalPort(); - } - } - else { - ParametersList parametersList = extensionsJP.getVMParametersList(); - final ParametersList data = myEnv.getUserData(ExternalSystemTaskExecutionSettings.JVM_AGENT_SETUP_KEY); - if (data != null) { - parametersList.addAll(data.getList()); - } - for (String parameter : parametersList.getList()) { - if (parameter.startsWith("-agentlib:")) continue; - if (parameter.startsWith("-agentpath:")) continue; - if (parameter.startsWith("-javaagent:")) continue; - throw new ExecutionException(ExternalSystemBundle.message("run.invalid.jvm.agent.configuration", parameter)); - } - jvmAgentSetup = parametersList.getParametersString(); - } + String jvmAgentSetup = getJvmAgentSetup(); ApplicationManager.getApplication().assertIsDispatchThread(); FileDocumentManager.getInstance().saveAllDocuments(); @@ -468,6 +447,42 @@ public class ExternalSystemRunConfiguration extends LocatableConfigurationBase i return executionResult; } + @Nullable + private String getJvmAgentSetup() throws ExecutionException { + // todo [Vlad, IDEA-187832]: extract to `external-system-java` module + if(!ExternalSystemApiUtil.isJavaCompatibleIde()) return null; + + final JavaParameters extensionsJP = new JavaParameters(); + final RunConfigurationExtension[] extensions = Extensions.getExtensions(RunConfigurationExtension.EP_NAME); + for (RunConfigurationExtension ext : extensions) { + ext.updateJavaParameters(myConfiguration, extensionsJP, myEnv.getRunnerSettings()); + } + + String jvmAgentSetup; + + if (myDebugPort > 0) { + jvmAgentSetup = DEBUG_SETUP_PREFIX + myDebugPort; + if (getForkSocket() != null) { + jvmAgentSetup += " -forkSocket" + getForkSocket().getLocalPort(); + } + } + else { + ParametersList parametersList = extensionsJP.getVMParametersList(); + final ParametersList data = myEnv.getUserData(ExternalSystemTaskExecutionSettings.JVM_AGENT_SETUP_KEY); + if (data != null) { + parametersList.addAll(data.getList()); + } + for (String parameter : parametersList.getList()) { + if (parameter.startsWith("-agentlib:")) continue; + if (parameter.startsWith("-agentpath:")) continue; + if (parameter.startsWith("-javaagent:")) continue; + throw new ExecutionException(ExternalSystemBundle.message("run.invalid.jvm.agent.configuration", parameter)); + } + jvmAgentSetup = parametersList.getParametersString(); + } + return jvmAgentSetup; + } + private BuildProgressListener createBuildView(ExternalSystemTaskId id, String executionName, String workingDir, diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/AbstractModuleDataService.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/AbstractModuleDataService.java index fe45effebb2c..d53f1a3dc067 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/AbstractModuleDataService.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/project/manage/AbstractModuleDataService.java @@ -105,7 +105,11 @@ public abstract class AbstractModuleDataService extends Ab setModuleOptions(module, node); ModifiableRootModel modifiableRootModel = modelsProvider.getModifiableRootModel(module); syncPaths(module, modifiableRootModel, node.getData()); - setLanguageLevel(modifiableRootModel, node.getData()); + + if(ModuleTypeId.JAVA_MODULE.equals(module.getModuleTypeName())) { + // todo [Vlad, IDEA-187832]: extract to `external-system-java` module + setLanguageLevel(modifiableRootModel, node.getData()); + } setSdk(modifiableRootModel, node.getData()); } } diff --git a/platform/platform-resources/src/META-INF/ExternalSystemExtensionPoints.xml b/platform/platform-resources/src/META-INF/ExternalSystemExtensionPoints.xml index ae12151e0429..aadd25701337 100644 --- a/platform/platform-resources/src/META-INF/ExternalSystemExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/ExternalSystemExtensionPoints.xml @@ -1,35 +1,38 @@ - - + - - - - - - - - - - - - - - - + + \ No newline at end of file diff --git a/plugins/gradle/java/src/config/GradleResourceCompilerConfigurationGenerator.java b/plugins/gradle/java/src/config/GradleResourceCompilerConfigurationGenerator.java index 9fa38bafb7db..aa08a95de091 100644 --- a/plugins/gradle/java/src/config/GradleResourceCompilerConfigurationGenerator.java +++ b/plugins/gradle/java/src/config/GradleResourceCompilerConfigurationGenerator.java @@ -273,11 +273,11 @@ public class GradleResourceCompilerConfigurationGenerator { rootConfiguration.targetPath = FileUtil.toSystemIndependentName(target); rootConfiguration.includes.clear(); - for (String include : directorySet.getIncludes()) { + for (String include : directorySet.getPatterns().getIncludes()) { rootConfiguration.includes.add(include.trim()); } rootConfiguration.excludes.clear(); - for (String exclude : directorySet.getExcludes()) { + for (String exclude : directorySet.getPatterns().getExcludes()) { rootConfiguration.excludes.add(exclude.trim()); } if (sourcesDirectorySet != null && sourcesDirectorySet.getSrcDirs().contains(file)) { diff --git a/plugins/gradle/native/intellij.gradle.native.iml b/plugins/gradle/native/intellij.gradle.native.iml new file mode 100644 index 000000000000..417f3fe90af0 --- /dev/null +++ b/plugins/gradle/native/intellij.gradle.native.iml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/gradle/native/resources/META-INF/gradle-native-plugin.xml b/plugins/gradle/native/resources/META-INF/gradle-native-plugin.xml new file mode 100644 index 000000000000..e2c86d1a939e --- /dev/null +++ b/plugins/gradle/native/resources/META-INF/gradle-native-plugin.xml @@ -0,0 +1,24 @@ + + + + + org.jetbrains.plugins.gradle + + + + + diff --git a/plugins/gradle/native/src/project/GradleNativeProjectResolver.java b/plugins/gradle/native/src/project/GradleNativeProjectResolver.java new file mode 100644 index 000000000000..924d0786f02e --- /dev/null +++ b/plugins/gradle/native/src/project/GradleNativeProjectResolver.java @@ -0,0 +1,66 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.gradle.nativeplatform.project; + +import com.intellij.openapi.externalSystem.model.DataNode; +import com.intellij.openapi.externalSystem.model.Key; +import com.intellij.openapi.externalSystem.model.ProjectKeys; +import com.intellij.openapi.externalSystem.model.project.ContentRootData; +import com.intellij.openapi.externalSystem.model.project.ExternalSystemSourceType; +import com.intellij.openapi.externalSystem.model.project.ModuleData; +import com.intellij.openapi.externalSystem.util.ExternalSystemConstants; +import com.intellij.openapi.externalSystem.util.Order; +import com.intellij.util.containers.ContainerUtil; +import org.gradle.tooling.model.idea.IdeaModule; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.gradle.nativeplatform.tooling.builder.CppModelBuilder; +import org.jetbrains.plugins.gradle.nativeplatform.tooling.model.CppProject; +import org.jetbrains.plugins.gradle.nativeplatform.tooling.model.SourceFolder; +import org.jetbrains.plugins.gradle.nativeplatform.tooling.model.impl.CppProjectImpl; +import org.jetbrains.plugins.gradle.service.project.AbstractProjectResolverExtension; +import org.jetbrains.plugins.gradle.util.GradleConstants; + +import java.io.File; +import java.util.Collections; +import java.util.Set; + +/** + * @author Vladislav.Soroka + */ +@Order(ExternalSystemConstants.UNORDERED) +public class GradleNativeProjectResolver extends AbstractProjectResolverExtension { + @NotNull public static final Key CPP_PROJECT = Key.create(CppProject.class, ProjectKeys.MODULE.getProcessingWeight() + 1); + + @Override + public void populateModuleContentRoots(@NotNull IdeaModule gradleModule, @NotNull DataNode ideModule) { + CppProject cppProject = resolverCtx.getExtraProject(gradleModule, CppProject.class); + if (cppProject != null) { + // store a local process copy of the object to get rid of proxy types for further serialization + ideModule.createChild(CPP_PROJECT, new CppProjectImpl(cppProject)); + + Set sourceFolders = cppProject.getSourceFolders(); + for (SourceFolder folder : sourceFolders) { + File baseDir = folder.getBaseDir(); + ContentRootData ideContentRoot = new ContentRootData(GradleConstants.SYSTEM_ID, baseDir.getAbsolutePath()); + ideContentRoot.storePath(ExternalSystemSourceType.SOURCE, baseDir.getAbsolutePath()); + ideModule.createChild(ProjectKeys.CONTENT_ROOT, ideContentRoot); + } + } + + nextResolver.populateModuleContentRoots(gradleModule, ideModule); + } + + @NotNull + @Override + public Set getExtraProjectModelClasses() { + return Collections.singleton(CppProject.class); + } + + @NotNull + @Override + public Set getToolingExtensionsClasses() { + return ContainerUtil.set( + // native-gradle-tooling jar + CppModelBuilder.class + ); + } +} diff --git a/plugins/gradle/native/tooling/intellij.gradle.native.tooling.iml b/plugins/gradle/native/tooling/intellij.gradle.native.tooling.iml new file mode 100644 index 000000000000..bb894f80c4cb --- /dev/null +++ b/plugins/gradle/native/tooling/intellij.gradle.native.tooling.iml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/gradle/native/tooling/resources/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService b/plugins/gradle/native/tooling/resources/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService new file mode 100644 index 000000000000..0754e2ae444c --- /dev/null +++ b/plugins/gradle/native/tooling/resources/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService @@ -0,0 +1,17 @@ +# Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +# +# Copyright 2000-2018 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. +# +org.jetbrains.plugins.gradle.nativeplatform.tooling.builder.CppModelBuilder diff --git a/plugins/gradle/native/tooling/src/builder/CppModelBuilder.java b/plugins/gradle/native/tooling/src/builder/CppModelBuilder.java new file mode 100644 index 000000000000..2ebdc7d2bb63 --- /dev/null +++ b/plugins/gradle/native/tooling/src/builder/CppModelBuilder.java @@ -0,0 +1,203 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.gradle.nativeplatform.tooling.builder; + +import org.gradle.api.Project; +import org.gradle.api.component.SoftwareComponent; +import org.gradle.api.file.FileCollection; +import org.gradle.api.file.RegularFileProperty; +import org.gradle.api.internal.file.FileCollectionInternal; +import org.gradle.api.internal.file.FileCollectionVisitor; +import org.gradle.api.internal.file.FileTreeInternal; +import org.gradle.api.internal.file.collections.DirectoryFileTree; +import org.gradle.api.provider.Provider; +import org.gradle.api.tasks.util.PatternSet; +import org.gradle.internal.impldep.org.apache.commons.lang.StringUtils; +import org.gradle.internal.os.OperatingSystem; +import org.gradle.language.cpp.CppBinary; +import org.gradle.language.cpp.CppComponent; +import org.gradle.language.cpp.CppSharedLibrary; +import org.gradle.language.cpp.CppStaticLibrary; +import org.gradle.language.cpp.plugins.CppBasePlugin; +import org.gradle.language.cpp.tasks.CppCompile; +import org.gradle.language.nativeplatform.ComponentWithExecutable; +import org.gradle.nativeplatform.tasks.LinkExecutable; +import org.gradle.nativeplatform.toolchain.Clang; +import org.gradle.nativeplatform.toolchain.Gcc; +import org.gradle.nativeplatform.toolchain.NativeToolChain; +import org.gradle.nativeplatform.toolchain.internal.ToolType; +import org.gradle.nativeplatform.toolchain.internal.tools.CommandLineToolSearchResult; +import org.gradle.nativeplatform.toolchain.internal.tools.ToolSearchPath; +import org.gradle.util.GradleVersion; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.gradle.model.FilePatternSetImpl; +import org.jetbrains.plugins.gradle.nativeplatform.tooling.model.CompilerDetails; +import org.jetbrains.plugins.gradle.nativeplatform.tooling.model.CppBinary.TargetType; +import org.jetbrains.plugins.gradle.nativeplatform.tooling.model.CppProject; +import org.jetbrains.plugins.gradle.nativeplatform.tooling.model.LinkerDetails; +import org.jetbrains.plugins.gradle.nativeplatform.tooling.model.impl.*; +import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder; +import org.jetbrains.plugins.gradle.tooling.ModelBuilderService; + +import java.io.File; +import java.util.*; + +/** + * The prototype of the C++ project gradle tooling model builder. + * This implementation should be moved or replaced with the similar model builder from the Gradle distribution. + * + * @author Vladislav.Soroka + */ +public class CppModelBuilder implements ModelBuilderService { + + @Override + public boolean canBuild(String modelName) { + return CppProject.class.getName().equals(modelName); + } + + @Nullable + @Override + public Object buildAll(final String modelName, final Project project) { + final CppBasePlugin cppPlugin = project.getPlugins().findPlugin(CppBasePlugin.class); + if (cppPlugin == null) return null; + + final CppProjectImpl cppProject = new CppProjectImpl(); + for (SoftwareComponent component : project.getComponents()) { + if (component instanceof CppComponent) { + File cppCompilerExecutable = null; + CppComponent cppComponent = (CppComponent)component; + for (CppBinary cppBinary : cppComponent.getBinaries().get()) { + if (cppCompilerExecutable == null) { + cppCompilerExecutable = findCppCompilerExecutable(cppBinary); + } + + List compilerArgs = new ArrayList(); + Set compileIncludePath = cppBinary.getCompileIncludePath().getFiles(); + + Set sources = cppBinary.getCppSource().getFiles(); + String baseName = cppBinary.getBaseName().getOrElse(""); + String variantName = StringUtils.removeStart(cppBinary.getName(), "main"); + String compileTaskName = null; + Set systemIncludes = new LinkedHashSet(); + Provider compileTask = cppBinary.getCompileTask(); + if (compileTask.isPresent()) { + CppCompile cppCompile = compileTask.get(); + compileTaskName = cppCompile.getPath(); + compilerArgs.addAll(cppCompile.getCompilerArgs().getOrElse(Collections.emptyList())); + systemIncludes.addAll(cppCompile.getIncludes().getFiles()); + } + + File executableFile = null; + String linkTaskName = null; + boolean isExecutable = cppBinary instanceof ComponentWithExecutable; + if (isExecutable) { + Provider fileProvider = ((ComponentWithExecutable)cppBinary).getLinkTask(); + if (fileProvider.isPresent()) { + LinkExecutable linkExecutable = fileProvider.get(); + linkTaskName = linkExecutable.getPath(); + executableFile = getExecutableFile(linkExecutable); + } + } + + TargetType targetType = null; + if (isExecutable) { + targetType = TargetType.EXECUTABLE; + } + else if (cppBinary instanceof CppSharedLibrary) { + targetType = TargetType.SHARED_LIBRARY; + } + else if (cppBinary instanceof CppStaticLibrary) { + targetType = TargetType.STATIC_LIBRARY; + } + + // resolve compiler working dir as compiler executable file parent dir + // https://github.com/gradle/gradle/blob/7422d5fc2e04d564dfd73bc539a37b62f8e2113a/subprojects/platform-native/src/main/java/org/gradle/nativeplatform/toolchain/internal/metadata/AbstractMetadataProvider.java#L61 + File compilerWorkingDir = cppCompilerExecutable == null ? null : cppCompilerExecutable.getParentFile(); + CompilerDetails compilerDetails = new CompilerDetailsImpl( + compileTaskName, cppCompilerExecutable, compilerWorkingDir, compilerArgs, compileIncludePath, systemIncludes); + LinkerDetails linkerDetails = new LinkerDetailsImpl(linkTaskName, executableFile); + cppProject.addBinary(new CppBinaryImpl(baseName, variantName, sources, compilerDetails, linkerDetails, targetType)); + } + + addSourceFolders(cppProject, cppComponent); + } + } + + return cppProject; + } + + @Nullable + private static File getExecutableFile(LinkExecutable linkExecutable) { + File executableFile; + RegularFileProperty binaryFile = null; + if (GradleVersion.current().compareTo(GradleVersion.version("4.7")) < 0) { + binaryFile = linkExecutable.getBinaryFile(); + } + else { + try { + Object linkedFile = linkExecutable.getClass().getMethod("getLinkedFile").invoke(linkExecutable); + if (linkedFile instanceof RegularFileProperty) { + binaryFile = (RegularFileProperty)linkedFile; + } + } + catch (Exception e) { + //noinspection CallToPrintStackTrace + e.printStackTrace(); + } + } + executableFile = binaryFile != null ? binaryFile.getAsFile().getOrNull() : null; + return executableFile; + } + + private static void addSourceFolders(final CppProjectImpl cppProject, CppComponent cppComponent) { + for (File dir : cppComponent.getPrivateHeaderDirs()) { + cppProject.addSourceFolder( + new SourceFolderImpl(dir, new FilePatternSetImpl(Collections.emptySet(), Collections.emptySet()))); + } + + FileCollection cppSource = cppComponent.getCppSource(); + // try to resolve cpp source folders + ((FileCollectionInternal)cppSource).visitRootElements(new FileCollectionVisitor() { + @Override + public void visitCollection(FileCollectionInternal internal) { + } + + @Override + public void visitTree(FileTreeInternal internal) { + } + + @Override + public void visitDirectoryTree(DirectoryFileTree tree) { + File dir = tree.getDir(); + PatternSet patterns = tree.getPatterns(); + cppProject.addSourceFolder(new SourceFolderImpl(dir, new FilePatternSetImpl(patterns.getIncludes(), patterns.getExcludes()))); + } + }); + } + + @Nullable + private static File findCppCompilerExecutable(CppBinary cppBinary) { + NativeToolChain toolChain = cppBinary.getToolChain(); + String exeName; + if (toolChain instanceof Gcc) { + exeName = "g++"; + } + else if (toolChain instanceof Clang) { + exeName = "clang++"; + } + else { + return null; + } + ToolSearchPath toolSearchPath = new ToolSearchPath(OperatingSystem.current()); + CommandLineToolSearchResult searchResult = toolSearchPath.locate(ToolType.CPP_COMPILER, exeName); + return searchResult.isAvailable() ? searchResult.getTool() : null; + } + + @NotNull + @Override + public ErrorMessageBuilder getErrorMessageBuilder(@NotNull Project project, @NotNull Exception e) { + return ErrorMessageBuilder.create( + project, e, "C++ project import errors" + ).withDescription("Unable to import C++ project"); + } +} diff --git a/plugins/gradle/native/tooling/src/model/CompilerDetails.java b/plugins/gradle/native/tooling/src/model/CompilerDetails.java new file mode 100644 index 000000000000..db7d9e83e1fa --- /dev/null +++ b/plugins/gradle/native/tooling/src/model/CompilerDetails.java @@ -0,0 +1,24 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.gradle.nativeplatform.tooling.model; + +import java.io.File; +import java.io.Serializable; +import java.util.List; +import java.util.Set; + +/** + * @author Vladislav.Soroka + */ +public interface CompilerDetails extends Serializable { + String getCompileTaskName(); + + Set getIncludePath(); + + Set getSystemIncludes(); + + File getExecutable(); + + File getWorkingDir(); + + List getArgs(); +} diff --git a/plugins/gradle/native/tooling/src/model/CppBinary.java b/plugins/gradle/native/tooling/src/model/CppBinary.java new file mode 100644 index 000000000000..b010751f3aaa --- /dev/null +++ b/plugins/gradle/native/tooling/src/model/CppBinary.java @@ -0,0 +1,44 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.gradle.nativeplatform.tooling.model; + +import java.io.File; +import java.io.Serializable; +import java.util.List; +import java.util.Set; + +/** + * @author Vladislav.Soroka + */ +public interface CppBinary extends Serializable { + /** + * Returns the base name of this component. This is used by Gradle to calculate output file names. + */ + String getBaseName(); + + /** + * Returns the binary variant name, e.g. Debug, Release etc. + */ + String getVariantName(); + + Set getSources(); + + CompilerDetails getCompilerDetails(); + + Set getCompileIncludePath(); + + File getCompilerExecutable(); + + List getCompilerArgs(); + + LinkerDetails getLinkerDetails(); + + File getOutputFile(); + + TargetType getTargetType(); + + enum TargetType { + EXECUTABLE, + STATIC_LIBRARY, + SHARED_LIBRARY + } +} diff --git a/plugins/gradle/native/tooling/src/model/CppProject.java b/plugins/gradle/native/tooling/src/model/CppProject.java new file mode 100644 index 000000000000..bb5dddac2e07 --- /dev/null +++ b/plugins/gradle/native/tooling/src/model/CppProject.java @@ -0,0 +1,15 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.gradle.nativeplatform.tooling.model; + + +import java.io.Serializable; +import java.util.Set; + +/** + * @author Vladislav.Soroka + */ +public interface CppProject extends Serializable { + Set getSourceFolders(); + + Set getBinaries(); +} diff --git a/plugins/gradle/native/tooling/src/model/LinkerDetails.java b/plugins/gradle/native/tooling/src/model/LinkerDetails.java new file mode 100644 index 000000000000..c79655e8f151 --- /dev/null +++ b/plugins/gradle/native/tooling/src/model/LinkerDetails.java @@ -0,0 +1,14 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.gradle.nativeplatform.tooling.model; + +import java.io.File; +import java.io.Serializable; + +/** + * @author Vladislav.Soroka + */ +public interface LinkerDetails extends Serializable { + File getOutputFile(); + + String getLinkTaskName(); +} diff --git a/plugins/gradle/native/tooling/src/model/SourceFolder.java b/plugins/gradle/native/tooling/src/model/SourceFolder.java new file mode 100644 index 000000000000..e7ecff078ac9 --- /dev/null +++ b/plugins/gradle/native/tooling/src/model/SourceFolder.java @@ -0,0 +1,16 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.gradle.nativeplatform.tooling.model; + +import org.jetbrains.plugins.gradle.model.FilePatternSet; + +import java.io.File; +import java.io.Serializable; + +/** + * @author Vladislav.Soroka + */ +public interface SourceFolder extends Serializable { + File getBaseDir(); + + FilePatternSet getPatterns(); +} diff --git a/plugins/gradle/native/tooling/src/model/impl/CompilerDetailsImpl.java b/plugins/gradle/native/tooling/src/model/impl/CompilerDetailsImpl.java new file mode 100644 index 000000000000..edcfec23348b --- /dev/null +++ b/plugins/gradle/native/tooling/src/model/impl/CompilerDetailsImpl.java @@ -0,0 +1,72 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.gradle.nativeplatform.tooling.model.impl; + +import org.jetbrains.plugins.gradle.nativeplatform.tooling.model.CompilerDetails; + +import java.io.File; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; + +/** + * @author Vladislav.Soroka + */ +public class CompilerDetailsImpl implements CompilerDetails { + + private final Set myIncludePath; + private final Set mySystemIncludes; + private final String myCompileTaskName; + private final File myExecutable; + private final File myWorkingDir; + private final List myArgs; + + public CompilerDetailsImpl(String compileTaskName, + File executable, + File workingDir, + List args, + Set includePath, + Set systemIncludes) { + myCompileTaskName = compileTaskName; + myExecutable = executable; + myWorkingDir = workingDir; + myArgs = args; + myIncludePath = new LinkedHashSet(includePath); + mySystemIncludes = new LinkedHashSet(systemIncludes); + } + + public CompilerDetailsImpl(CompilerDetails details) { + this(details.getCompileTaskName(), details.getExecutable(), details.getWorkingDir(), details.getArgs(), + details.getIncludePath(), details.getSystemIncludes()); + } + + @Override + public String getCompileTaskName() { + return myCompileTaskName; + } + + @Override + public Set getIncludePath() { + return Collections.unmodifiableSet(myIncludePath); + } + + @Override + public Set getSystemIncludes() { + return Collections.unmodifiableSet(mySystemIncludes); + } + + @Override + public File getExecutable() { + return myExecutable; + } + + @Override + public File getWorkingDir() { + return myWorkingDir; + } + + @Override + public List getArgs() { + return Collections.unmodifiableList(myArgs); + } +} diff --git a/plugins/gradle/native/tooling/src/model/impl/CppBinaryImpl.java b/plugins/gradle/native/tooling/src/model/impl/CppBinaryImpl.java new file mode 100644 index 000000000000..ab6272989f11 --- /dev/null +++ b/plugins/gradle/native/tooling/src/model/impl/CppBinaryImpl.java @@ -0,0 +1,89 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.gradle.nativeplatform.tooling.model.impl; + +import org.jetbrains.plugins.gradle.nativeplatform.tooling.model.CompilerDetails; +import org.jetbrains.plugins.gradle.nativeplatform.tooling.model.CppBinary; +import org.jetbrains.plugins.gradle.nativeplatform.tooling.model.LinkerDetails; + +import java.io.File; +import java.util.*; + +/** + * @author Vladislav.Soroka + */ +public class CppBinaryImpl implements CppBinary { + private final String myBaseName; + private final String myVariantName; + private final Set mySources; + private final CompilerDetails myCompilerDetails; + private final LinkerDetails myLinkerDetails; + private final TargetType myTargetType; + + public CppBinaryImpl(String baseName, String variantName, + Collection sources, + CompilerDetails compilerDetails, + LinkerDetails linkerDetails, + TargetType targetType) { + myBaseName = baseName; + myVariantName = variantName; + mySources = new LinkedHashSet(sources); + myCompilerDetails = compilerDetails; + myLinkerDetails = linkerDetails; + myTargetType = targetType; + } + + public CppBinaryImpl(CppBinary binary) { + this(binary.getBaseName(), binary.getVariantName(), binary.getSources(), + new CompilerDetailsImpl(binary.getCompilerDetails()), new LinkerDetailsImpl(binary.getLinkerDetails()), binary.getTargetType()); + } + + @Override + public String getBaseName() { + return myBaseName; + } + + @Override + public String getVariantName() { + return myVariantName; + } + + @Override + public Set getSources() { + return Collections.unmodifiableSet(mySources); + } + + @Override + public CompilerDetails getCompilerDetails() { + return myCompilerDetails; + } + + @Override + public Set getCompileIncludePath() { + return myCompilerDetails.getIncludePath(); + } + + @Override + public File getCompilerExecutable() { + return myCompilerDetails.getExecutable(); + } + + @Override + public List getCompilerArgs() { + return myCompilerDetails.getArgs(); + } + + @Override + public LinkerDetails getLinkerDetails() { + return myLinkerDetails; + } + + @Override + public File getOutputFile() { + return myLinkerDetails.getOutputFile(); + } + + @Override + public TargetType getTargetType() { + return myTargetType; + } +} diff --git a/plugins/gradle/native/tooling/src/model/impl/CppProjectImpl.java b/plugins/gradle/native/tooling/src/model/impl/CppProjectImpl.java new file mode 100644 index 000000000000..0b824063896f --- /dev/null +++ b/plugins/gradle/native/tooling/src/model/impl/CppProjectImpl.java @@ -0,0 +1,49 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.gradle.nativeplatform.tooling.model.impl; + +import org.jetbrains.plugins.gradle.nativeplatform.tooling.model.CppBinary; +import org.jetbrains.plugins.gradle.nativeplatform.tooling.model.CppProject; +import org.jetbrains.plugins.gradle.nativeplatform.tooling.model.SourceFolder; + +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Set; + +/** + * @author Vladislav.Soroka + */ +public class CppProjectImpl implements CppProject { + + private final Set mySourceFolders = new LinkedHashSet(); + private final Set binaries = new LinkedHashSet(); + + public CppProjectImpl() { + } + + public CppProjectImpl(CppProject cppProject) { + for (CppBinary binary : cppProject.getBinaries()) { + addBinary(new CppBinaryImpl(binary)); + } + for (SourceFolder sourceFolder : cppProject.getSourceFolders()) { + addSourceFolder(new SourceFolderImpl(sourceFolder)); + } + } + + @Override + public Set getSourceFolders() { + return Collections.unmodifiableSet(mySourceFolders); + } + + public void addSourceFolder(SourceFolder folder) { + mySourceFolders.add(folder); + } + + @Override + public Set getBinaries() { + return Collections.unmodifiableSet(binaries); + } + + public void addBinary(CppBinary binary) { + binaries.add(binary); + } +} diff --git a/plugins/gradle/native/tooling/src/model/impl/LinkerDetailsImpl.java b/plugins/gradle/native/tooling/src/model/impl/LinkerDetailsImpl.java new file mode 100644 index 000000000000..c884c241c3e5 --- /dev/null +++ b/plugins/gradle/native/tooling/src/model/impl/LinkerDetailsImpl.java @@ -0,0 +1,33 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.gradle.nativeplatform.tooling.model.impl; + +import org.jetbrains.plugins.gradle.nativeplatform.tooling.model.LinkerDetails; + +import java.io.File; + +/** + * @author Vladislav.Soroka + */ +public class LinkerDetailsImpl implements LinkerDetails { + private final String myLinkTaskName; + private final File myOutputFile; + + public LinkerDetailsImpl(String linkTaskName, File outputFile) { + myLinkTaskName = linkTaskName; + myOutputFile = outputFile; + } + + public LinkerDetailsImpl(LinkerDetails details) { + this(details.getLinkTaskName(), details.getOutputFile()); + } + + @Override + public File getOutputFile() { + return myOutputFile; + } + + @Override + public String getLinkTaskName() { + return myLinkTaskName; + } +} diff --git a/plugins/gradle/native/tooling/src/model/impl/SourceFolderImpl.java b/plugins/gradle/native/tooling/src/model/impl/SourceFolderImpl.java new file mode 100644 index 000000000000..8b09e905e4d4 --- /dev/null +++ b/plugins/gradle/native/tooling/src/model/impl/SourceFolderImpl.java @@ -0,0 +1,56 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.gradle.nativeplatform.tooling.model.impl; + +import org.jetbrains.plugins.gradle.model.FilePatternSet; +import org.jetbrains.plugins.gradle.model.FilePatternSetImpl; +import org.jetbrains.plugins.gradle.nativeplatform.tooling.model.SourceFolder; + +import java.io.File; + +/** + * @author Vladislav.Soroka + */ +public class SourceFolderImpl implements SourceFolder { + private final File myBaseDir; + private final FilePatternSet myPatterns; + + public SourceFolderImpl(File dir, FilePatternSet patterns) { + myBaseDir = dir; + myPatterns = patterns; + } + + public SourceFolderImpl(SourceFolder folder) { + this(folder.getBaseDir(), folder.getPatterns() != null + ? new FilePatternSetImpl(folder.getPatterns().getIncludes(), folder.getPatterns().getExcludes()) : null); + } + + @Override + public File getBaseDir() { + return myBaseDir; + } + + @Override + public FilePatternSet getPatterns() { + return myPatterns; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + SourceFolderImpl folder = (SourceFolderImpl)o; + + if (myBaseDir != null ? !myBaseDir.equals(folder.myBaseDir) : folder.myBaseDir != null) return false; + if (myPatterns != null ? !myPatterns.equals(folder.myPatterns) : folder.myPatterns != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = myBaseDir != null ? myBaseDir.hashCode() : 0; + result = 31 * result + (myPatterns != null ? myPatterns.hashCode() : 0); + return result; + } +} diff --git a/plugins/gradle/plugin-resources/META-INF/plugin.xml b/plugins/gradle/plugin-resources/META-INF/plugin.xml index b46a0ca82e99..2c9c05c06b00 100644 --- a/plugins/gradle/plugin-resources/META-INF/plugin.xml +++ b/plugins/gradle/plugin-resources/META-INF/plugin.xml @@ -21,6 +21,9 @@ com.intellij.modules.lang + + + diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/GradleManager.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/GradleManager.java index 3ee7df89c6a5..44383c4b21bb 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/GradleManager.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/GradleManager.java @@ -22,6 +22,10 @@ import com.intellij.execution.configurations.SearchScopeProvider; import com.intellij.execution.configurations.SimpleJavaParameters; import com.intellij.execution.testframework.sm.runner.SMTRunnerConsoleProperties; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.extensions.ExtensionPoint; +import com.intellij.openapi.extensions.ExtensionPointListener; +import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.extensions.impl.ExtensionPointImpl; import com.intellij.openapi.externalSystem.ExternalSystemAutoImportAware; import com.intellij.openapi.externalSystem.ExternalSystemConfigurableAware; import com.intellij.openapi.externalSystem.ExternalSystemManager; @@ -60,6 +64,7 @@ import com.intellij.psi.search.GlobalSearchScope; import com.intellij.util.Function; import com.intellij.util.PathUtil; import com.intellij.util.PathsList; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.ContainerUtilRt; import com.intellij.util.messages.MessageBusConnection; import icons.GradleIcons; @@ -82,6 +87,7 @@ import javax.swing.*; import java.io.File; import java.io.IOException; import java.util.*; +import java.util.function.Predicate; import static com.intellij.openapi.util.io.FileUtil.pathsEqual; @@ -111,7 +117,33 @@ public class GradleManager @Override protected List compute() { List result = ContainerUtilRt.newArrayList(); - Collections.addAll(result, GradleProjectResolverExtension.EP_NAME.getExtensions()); + + // It's possible usecase when 'java' subsystem dependent plugins bundled with the non-java IDE using fat plugin distribution. + // This approach can lead to unwanted/incompatible extensions to be loaded. + // The workaround extensionsFilter should be removed when the IntelliJ java subsystem will become a regular plugin + // or those plugins will be fixed using the optional plugin dependency on 'org.jetbrains.plugins.gradle.java' + boolean isJavaIde = ExternalSystemApiUtil.isJavaCompatibleIde(); + if(!isJavaIde) { + ExtensionPoint point = + Extensions.getRootArea().getExtensionPoint(GradleProjectResolverExtension.EP_NAME); + if(point instanceof ExtensionPointImpl) { + ((ExtensionPointImpl)point).removeUnloadableExtensions(); + } + } + Set javaIdeDependentExtensions = ContainerUtil.set( + "org.jetbrains.kotlin.idea.configuration.KotlinGradleProjectResolverExtension", + "org.jetbrains.kotlin.kapt.idea.KaptProjectResolverExtension", + "org.jetbrains.kotlin.allopen.ide.AllOpenProjectResolverExtension", + "org.jetbrains.kotlin.noarg.ide.NoArgProjectResolverExtension", + "org.jetbrains.kotlin.samWithReceiver.ide.SamWithReceiverProjectResolverExtension" + ); + Predicate extensionsFilter = ext -> + isJavaIde || !javaIdeDependentExtensions.contains(ext.getClass().getName()); + + Arrays.stream(GradleProjectResolverExtension.EP_NAME.getExtensions()) + .filter(extensionsFilter) + .forEach(result::add); + ExternalSystemApiUtil.orderAwareSort(result); return result; } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java index e7e9b0f4209e..97285d81e3f3 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/GradleProjectResolver.java @@ -218,7 +218,12 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver buildActionExecutor = resolverCtx.getConnection().action(projectImportAction); diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/ExternalProjectSerializer.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/ExternalProjectSerializer.java index 0fa3323e4bb7..5774c9b33b19 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/ExternalProjectSerializer.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/data/ExternalProjectSerializer.java @@ -190,6 +190,16 @@ public class ExternalProjectSerializer { } ); + myKryo.register( + FilePatternSetImpl.class, + new FieldSerializer(myKryo, FilePatternSetImpl.class) { + @Override + protected FilePatternSetImpl create(Kryo kryo, Input input, Class type) { + return new FilePatternSetImpl(new LinkedHashSet<>(), new LinkedHashSet<>()); + } + } + ); + myKryo.register(LinkedHashSet.class, new CollectionSerializer() { @Override protected Collection create(Kryo kryo, Input input, Class type) { diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleProjectSettings.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleProjectSettings.java index eeb97fe8a81d..d63336fee280 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleProjectSettings.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/settings/GradleProjectSettings.java @@ -3,6 +3,7 @@ package org.jetbrains.plugins.gradle.settings; import com.intellij.openapi.externalSystem.service.execution.ExternalSystemJdkUtil; import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings; +import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil; import com.intellij.util.SmartList; import com.intellij.util.ThreeState; import com.intellij.util.containers.ContainerUtil; @@ -25,7 +26,7 @@ public class GradleProjectSettings extends ExternalProjectSettings { @Nullable private String myGradleJvm = ExternalSystemJdkUtil.USE_PROJECT_JDK; @Nullable private DistributionType distributionType; private boolean disableWrapperSourceDistributionNotification; - private boolean resolveModulePerSourceSet = true; + private boolean resolveModulePerSourceSet = ExternalSystemApiUtil.isJavaCompatibleIde(); @Nullable private CompositeBuild myCompositeBuild; private ThreeState storeProjectFilesExternally = ThreeState.NO; diff --git a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ExternalSourceDirectorySet.java b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ExternalSourceDirectorySet.java index 88b684b6faac..4e9676454b7a 100644 --- a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ExternalSourceDirectorySet.java +++ b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/ExternalSourceDirectorySet.java @@ -57,6 +57,9 @@ public interface ExternalSourceDirectorySet extends Serializable { @NotNull Set getIncludes(); + @NotNull + FilePatternSet getPatterns(); + @NotNull List getFilters(); } diff --git a/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/FilePatternSet.java b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/FilePatternSet.java new file mode 100644 index 000000000000..daf01cf112ae --- /dev/null +++ b/plugins/gradle/tooling-extension-api/src/org/jetbrains/plugins/gradle/model/FilePatternSet.java @@ -0,0 +1,13 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.gradle.model; + +import java.io.Serializable; +import java.util.Set; + +/** + * @author Vladislav.Soroka + */ +public interface FilePatternSet extends Serializable { + Set getIncludes(); + Set getExcludes(); +} diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultExternalSourceDirectorySet.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultExternalSourceDirectorySet.java index d102773caa53..09caf28d63e8 100644 --- a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultExternalSourceDirectorySet.java +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/DefaultExternalSourceDirectorySet.java @@ -33,10 +33,7 @@ public class DefaultExternalSourceDirectorySet implements ExternalSourceDirector private Set mySrcDirs; private File myOutputDir; private final List myGradleOutputDirs; - @NotNull - private Set myExcludes; - @NotNull - private Set myIncludes; + private final FilePatternSet myPatterns; @NotNull private List myFilters; @@ -44,10 +41,9 @@ public class DefaultExternalSourceDirectorySet implements ExternalSourceDirector public DefaultExternalSourceDirectorySet() { mySrcDirs = new HashSet(); - myExcludes = new HashSet(); - myIncludes = new HashSet(); myFilters = new ArrayList(); myGradleOutputDirs = new ArrayList(); + myPatterns = new FilePatternSetImpl(new LinkedHashSet(), new LinkedHashSet()); } public DefaultExternalSourceDirectorySet(ExternalSourceDirectorySet sourceDirectorySet) { @@ -57,8 +53,8 @@ public class DefaultExternalSourceDirectorySet implements ExternalSourceDirector myOutputDir = sourceDirectorySet.getOutputDir(); myGradleOutputDirs.addAll(sourceDirectorySet.getGradleOutputDirs()); - myExcludes = new HashSet(sourceDirectorySet.getExcludes()); - myIncludes = new HashSet(sourceDirectorySet.getIncludes()); + myPatterns.getIncludes().addAll(sourceDirectorySet.getPatterns().getIncludes()); + myPatterns.getExcludes().addAll(sourceDirectorySet.getPatterns().getExcludes()); for (ExternalFilter filter : sourceDirectorySet.getFilters()) { myFilters.add(new DefaultExternalFilter(filter)); } @@ -117,28 +113,36 @@ public class DefaultExternalSourceDirectorySet implements ExternalSourceDirector return myInheritedCompilerOutput; } - public void setInheritedCompilerOutput(boolean inheritedCompilerOutput) { - myInheritedCompilerOutput = inheritedCompilerOutput; + @NotNull + @Override + public Set getExcludes() { + return myPatterns.getExcludes(); + } + + public void setExcludes(Set excludes) { + myPatterns.getExcludes().clear(); + myPatterns.getExcludes().addAll(excludes); } @NotNull @Override public Set getIncludes() { - return myIncludes; + return myPatterns.getIncludes(); } - public void setIncludes(@NotNull Set includes) { - myIncludes = includes; + public void setIncludes(Set includes) { + myPatterns.getIncludes().clear(); + myPatterns.getIncludes().addAll(includes); } @NotNull @Override - public Set getExcludes() { - return myExcludes; + public FilePatternSet getPatterns() { + return myPatterns; } - public void setExcludes(@NotNull Set excludes) { - myExcludes = excludes; + public void setInheritedCompilerOutput(boolean inheritedCompilerOutput) { + myInheritedCompilerOutput = inheritedCompilerOutput; } @NotNull diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/FilePatternSetImpl.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/FilePatternSetImpl.java new file mode 100644 index 000000000000..46c8f8f2c07c --- /dev/null +++ b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/model/FilePatternSetImpl.java @@ -0,0 +1,47 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package org.jetbrains.plugins.gradle.model; + +import java.util.Set; + +/** + * @author Vladislav.Soroka + */ +public class FilePatternSetImpl implements FilePatternSet { + private final Set includes; + private final Set excludes; + + public FilePatternSetImpl(Set includes, Set excludes) { + this.includes = includes; + this.excludes = excludes; + } + + @Override + public Set getIncludes() { + return includes; + } + + @Override + public Set getExcludes() { + return excludes; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + FilePatternSetImpl set = (FilePatternSetImpl)o; + + if (includes != null ? !includes.equals(set.includes) : set.includes != null) return false; + if (excludes != null ? !excludes.equals(set.excludes) : set.excludes != null) return false; + + return true; + } + + @Override + public int hashCode() { + int result = includes != null ? includes.hashCode() : 0; + result = 31 * result + (excludes != null ? excludes.hashCode() : 0); + return result; + } +}