Merge remote-tracking branch 'origin/master'
@@ -1,31 +1,35 @@
|
||||
<component name="libraryTable">
|
||||
<library name="Gradle">
|
||||
<CLASSES>
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-tooling-api-2.13.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-core-2.13.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-messaging-2.13.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-model-core-2.13.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-model-groovy-2.13.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-wrapper-2.13.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-base-services-2.13.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-base-services-groovy-2.13.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-native-2.13.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-resources-2.13.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-cli-2.13.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-tooling-api-2.14.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-core-2.14.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-messaging-2.14.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-model-core-2.14.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-model-groovy-2.14.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-wrapper-2.14.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-base-services-2.14.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-base-services-groovy-2.14.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-process-services-2.14.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-native-2.14.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-resources-2.14.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-cli-2.14.1.jar!/" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-logging-2.14.1.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-2.13-src.zip!/gradle-2.13/subprojects/tooling-api/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-2.13-src.zip!/gradle-2.13/subprojects/core/src/main/groovy" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-2.13-src.zip!/gradle-2.13/subprojects/model-core/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-2.13-src.zip!/gradle-2.13/subprojects/model-groovy/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-2.13-src.zip!/gradle-2.13/subprojects/messaging/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-2.13-src.zip!/gradle-2.13/subprojects/wrapper/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-2.13-src.zip!/gradle-2.13/subprojects/base-services/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-2.13-src.zip!/gradle-2.13/subprojects/base-services-groovy/src/main/groovy" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-2.13-src.zip!/gradle-2.13/subprojects/native/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-2.13-src.zip!/gradle-2.13/subprojects/resources/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-2.13-src.zip!/gradle-2.13/subprojects/cli/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-2.14.1-src.zip!/gradle-2.14.1/subprojects/tooling-api/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-2.14.1-src.zip!/gradle-2.14.1/subprojects/core/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-2.14.1-src.zip!/gradle-2.14.1/subprojects/model-core/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-2.14.1-src.zip!/gradle-2.14.1/subprojects/model-groovy/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-2.14.1-src.zip!/gradle-2.14.1/subprojects/messaging/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-2.14.1-src.zip!/gradle-2.14.1/subprojects/wrapper/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-2.14.1-src.zip!/gradle-2.14.1/subprojects/base-services/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-2.14.1-src.zip!/gradle-2.14.1/subprojects/base-services-groovy/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-2.14.1-src.zip!/gradle-2.14.1/subprojects/process-services/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-2.14.1-src.zip!/gradle-2.14.1/subprojects/native/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-2.14.1-src.zip!/gradle-2.14.1/subprojects/resources/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-2.14.1-src.zip!/gradle-2.14.1/subprojects/cli/src/main/java" />
|
||||
<root url="jar://$PROJECT_DIR$/plugins/gradle/lib/gradle-2.14.1-src.zip!/gradle-2.14.1/subprojects/logging/src/main/java" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
@@ -125,9 +125,9 @@ class CommunityLibraryLicenses {
|
||||
new LibraryLicense(name: "Gherkin", libraryName: "Gherkin", version: "2.12.2", license: "MIT",
|
||||
licenseUrl: "http://www.apache.org/licenses/LICENSE-2.0.txt", url: "https://github.com/cucumber/gherkin"),
|
||||
new LibraryLicense(name: "Google Feedback", libraryName: "GoogleFeedback.jar", version: "", license: "TBD"),
|
||||
new LibraryLicense(name: "gradle-tooling-api-2.13.jar", version: "2.13", license: "Apache 2.0", url: "http://gradle.org/",
|
||||
new LibraryLicense(name: "gradle-tooling-api-2.14.1.jar", version: "2.14.1", license: "Apache 2.0", url: "http://gradle.org/",
|
||||
licenseUrl: "http://gradle.org/license"),
|
||||
new LibraryLicense(name: "Gradle", version: "2.13", license: "Apache 2.0", url: "http://gradle.org/",
|
||||
new LibraryLicense(name: "Gradle", version: "2.14.1", license: "Apache 2.0", url: "http://gradle.org/",
|
||||
licenseUrl: "http://gradle.org/license"),
|
||||
new LibraryLicense(name: "GradleGuava", version: "14.0.1", license: "Apache 2.0", url: "http://code.google.com/p/guava-libraries/",
|
||||
licenseUrl: "http://apache.org/licenses/LICENSE-2.0"),
|
||||
|
||||
@@ -24,6 +24,10 @@ target('default': 'Downloads custom JRE build from Teamcity server') {
|
||||
echo "Unsupported platform, JRE download skipped"
|
||||
return
|
||||
}
|
||||
if (jreArchitecture == "disable") {
|
||||
echo "JRE update disabled"
|
||||
return
|
||||
}
|
||||
if (!(jreArchitecture == "64" || jreArchitecture == "32" && platform == "win")) {
|
||||
echo "Acceptable architecture (32 or 64 bit) is not defined, JRE download skipped"
|
||||
return
|
||||
|
||||
|
Before Width: | Height: | Size: 217 B After Width: | Height: | Size: 179 B |
@@ -0,0 +1,9 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<title>ImagesFileType</title>
|
||||
<g>
|
||||
<polygon points="6 0 2 4 6 4 6 0" fill="#9aa7b0" opacity="0.7" style="isolation: isolate"/>
|
||||
<path d="M7,0V5H2V15H13V0H7Zm5,14H3V6h9v8Z" fill="#9aa7b0" opacity="0.7" style="isolation: isolate"/>
|
||||
<path d="M11,13H4V11s2.06361-1.89568,3-1a9.5647,9.5647,0,0,0,4,2v1Z" fill="#62b543" opacity="0.8"/>
|
||||
<path d="M4,7v3S6.06348,8.10449,7,9a9.56218,9.56218,0,0,0,4,2V7H4ZM9.5,9A0.5,0.5,0,1,1,10,8.5,0.49987,0.49987,0,0,1,9.5,9Z" fill="#40b6e0" opacity="0.8"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 611 B |
|
Before Width: | Height: | Size: 384 B After Width: | Height: | Size: 272 B |
@@ -0,0 +1,9 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<title>ImagesFileType@2x</title>
|
||||
<g>
|
||||
<polygon points="12 0 4 8 12 8 12 0" fill="#9aa7b0" opacity="0.7" style="isolation: isolate"/>
|
||||
<path d="M14,0V10H4V30H26V0H14ZM24,28H6V12H24V28Z" fill="#9aa7b0" opacity="0.7" style="isolation: isolate"/>
|
||||
<path d="M22,26H8V22s4.12722-3.79136,6-2c3.06667,2.93333,8,4,8,4v2Z" fill="#62b543" opacity="0.8"/>
|
||||
<path d="M8,14v6s4.127-3.791,6-2c3.06641,2.93359,8,4,8,4V14H8Zm11,4a1,1,0,1,1,1-1A0.99974,0.99974,0,0,1,19,18Z" fill="#40b6e0" opacity="0.8"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 612 B |
@@ -22,6 +22,7 @@ import com.intellij.execution.runners.ExecutionEnvironment;
|
||||
import com.intellij.openapi.compiler.CompileScope;
|
||||
import com.intellij.openapi.compiler.CompileStatusNotification;
|
||||
import com.intellij.openapi.compiler.CompilerManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -45,6 +46,8 @@ import java.util.stream.Stream;
|
||||
* @since 5/11/2016
|
||||
*/
|
||||
public class InternalProjectTaskRunner extends ProjectTaskRunner {
|
||||
private static final Logger LOG = Logger.getInstance(InternalProjectTaskRunner.class);
|
||||
|
||||
@Override
|
||||
public void run(@NotNull Project project,
|
||||
@NotNull ProjectTaskContext context,
|
||||
@@ -89,39 +92,60 @@ public class InternalProjectTaskRunner extends ProjectTaskRunner {
|
||||
|
||||
|
||||
if (!ContainerUtil.isEmpty(buildTasks)) {
|
||||
List<Module> toMake = new SmartList<>();
|
||||
List<Module> toCompile = new SmartList<>();
|
||||
List<Module> modules = new SmartList<>();
|
||||
|
||||
Boolean isIncrementalBuild = null;
|
||||
Boolean includeDependentModules = null;
|
||||
Boolean includeRuntimeDependencies = null;
|
||||
|
||||
for (ProjectTask buildProjectTask : buildTasks) {
|
||||
ModuleBuildTask moduleBuildTask = (ModuleBuildTask)buildProjectTask;
|
||||
|
||||
if (moduleBuildTask.isIncrementalBuild()) {
|
||||
toMake.add(moduleBuildTask.getModule());
|
||||
assertModuleBuildSettings(moduleBuildTask, isIncrementalBuild, includeDependentModules, includeRuntimeDependencies);
|
||||
modules.add(moduleBuildTask.getModule());
|
||||
if (!moduleBuildTask.isIncrementalBuild()) {
|
||||
isIncrementalBuild = false;
|
||||
}
|
||||
else {
|
||||
toCompile.add(moduleBuildTask.getModule());
|
||||
if (moduleBuildTask.isIncludeDependentModules()) {
|
||||
includeDependentModules = true;
|
||||
}
|
||||
if (moduleBuildTask.isIncludeRuntimeDependencies()) {
|
||||
includeRuntimeDependencies = true;
|
||||
}
|
||||
}
|
||||
CompilerManager compilerManager = CompilerManager.getInstance(project);
|
||||
if (!toMake.isEmpty()) {
|
||||
CompileScope scope = createScope(project, compilerManager, context, toMake);
|
||||
// TODO handle multiple notifications
|
||||
CompileScope scope = createScope(
|
||||
compilerManager, context, modules, includeDependentModules != null, includeRuntimeDependencies != null);
|
||||
if (isIncrementalBuild == null) {
|
||||
compilerManager.make(scope, compileNotification);
|
||||
}
|
||||
if (!toCompile.isEmpty()) {
|
||||
CompileScope scope = createScope(project, compilerManager, context, toCompile);
|
||||
// TODO handle multiple notifications
|
||||
else {
|
||||
compilerManager.compile(scope, compileNotification);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void assertModuleBuildSettings(ModuleBuildTask moduleBuildTask,
|
||||
Boolean isIncrementalBuild,
|
||||
Boolean includeDependentModules,
|
||||
Boolean includeRuntimeDependencies) {
|
||||
if (isIncrementalBuild != null && moduleBuildTask.isIncrementalBuild()) {
|
||||
LOG.warn("Incremental build setting for the module '" + moduleBuildTask.getModule().getName() + "' will be ignored");
|
||||
}
|
||||
if (includeDependentModules != null && !moduleBuildTask.isIncludeDependentModules()) {
|
||||
LOG.warn("'Module '" + moduleBuildTask.getModule().getName() + "' will be built along with dependent modules");
|
||||
}
|
||||
if (includeRuntimeDependencies != null && !moduleBuildTask.isIncludeRuntimeDependencies()) {
|
||||
LOG.warn("'Module '" + moduleBuildTask.getModule().getName() + "' will be built along with runtime dependencies");
|
||||
}
|
||||
}
|
||||
|
||||
private static CompileScope createScope(Project project,
|
||||
CompilerManager compilerManager,
|
||||
private static CompileScope createScope(CompilerManager compilerManager,
|
||||
ProjectTaskContext context,
|
||||
Collection<Module> modules) {
|
||||
CompileScope scope = compilerManager.createModuleGroupCompileScope(project, modules.toArray(new Module[modules.size()]), true);
|
||||
Collection<Module> modules,
|
||||
boolean includeDependentModules,
|
||||
boolean includeRuntimeDependencies) {
|
||||
CompileScope scope = compilerManager.createModulesCompileScope(
|
||||
modules.toArray(new Module[modules.size()]), includeDependentModules, includeRuntimeDependencies);
|
||||
RunConfiguration configuration = context.getRunConfiguration();
|
||||
if (configuration != null) {
|
||||
scope.putUserData(CompilerManager.RUN_CONFIGURATION_KEY, configuration);
|
||||
|
||||
@@ -26,10 +26,21 @@ import org.jetbrains.annotations.NotNull;
|
||||
public class ModuleBuildTaskImpl extends AbstractBuildTask implements ModuleBuildTask {
|
||||
@NotNull
|
||||
private final Module myModule;
|
||||
private final boolean myIncludeDependentModules;
|
||||
private final boolean myIncludeRuntimeDependencies;
|
||||
|
||||
public ModuleBuildTaskImpl(@NotNull Module module, boolean isIncrementalBuild) {
|
||||
this(module, isIncrementalBuild, false, false);
|
||||
}
|
||||
|
||||
public ModuleBuildTaskImpl(@NotNull Module module,
|
||||
boolean isIncrementalBuild,
|
||||
boolean includeDependentModules,
|
||||
boolean includeRuntimeDependencies) {
|
||||
super(isIncrementalBuild);
|
||||
myModule = module;
|
||||
myIncludeDependentModules = includeDependentModules;
|
||||
myIncludeRuntimeDependencies = includeRuntimeDependencies;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -38,6 +49,16 @@ public class ModuleBuildTaskImpl extends AbstractBuildTask implements ModuleBuil
|
||||
return myModule;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIncludeDependentModules() {
|
||||
return myIncludeDependentModules;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIncludeRuntimeDependencies() {
|
||||
return myIncludeRuntimeDependencies;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getPresentableName() {
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.intellij.packaging.artifacts.Artifact;
|
||||
import com.intellij.task.*;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -50,12 +51,12 @@ public class ProjectTaskManagerImpl extends ProjectTaskManager {
|
||||
|
||||
@Override
|
||||
public void build(@NotNull Module[] modules, @Nullable ProjectTaskNotification callback) {
|
||||
run(createModulesBuildTask(true, modules), callback);
|
||||
run(createModulesBuildTask(modules, true, true, false), callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rebuild(@NotNull Module[] modules, @Nullable ProjectTaskNotification callback) {
|
||||
run(createModulesBuildTask(false, modules), callback);
|
||||
run(createModulesBuildTask(modules, false, false, false), callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -91,14 +92,26 @@ public class ProjectTaskManagerImpl extends ProjectTaskManager {
|
||||
|
||||
@Override
|
||||
public ProjectTask createAllModulesBuildTask(boolean isIncrementalBuild, Project project) {
|
||||
return createModulesBuildTask(isIncrementalBuild, ModuleManager.getInstance(project).getModules());
|
||||
return createModulesBuildTask(ModuleManager.getInstance(project).getModules(), isIncrementalBuild, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProjectTask createModulesBuildTask(boolean isIncrementalBuild, Module... modules) {
|
||||
public ProjectTask createModulesBuildTask(Module module,
|
||||
boolean isIncrementalBuild,
|
||||
boolean includeDependentModules,
|
||||
boolean includeRuntimeDependencies) {
|
||||
return createModulesBuildTask(ContainerUtil.ar(module), isIncrementalBuild, includeDependentModules, includeRuntimeDependencies);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProjectTask createModulesBuildTask(Module[] modules,
|
||||
boolean isIncrementalBuild,
|
||||
boolean includeDependentModules,
|
||||
boolean includeRuntimeDependencies) {
|
||||
return modules.length == 1
|
||||
? new ModuleBuildTaskImpl(modules[0], isIncrementalBuild)
|
||||
: new ProjectTaskList(map(list(modules), module -> new ModuleBuildTaskImpl(module, isIncrementalBuild)));
|
||||
? new ModuleBuildTaskImpl(modules[0], isIncrementalBuild, includeDependentModules, includeRuntimeDependencies)
|
||||
: new ProjectTaskList(map(list(modules), module ->
|
||||
new ModuleBuildTaskImpl(module, isIncrementalBuild, includeDependentModules, includeRuntimeDependencies)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,4 +25,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
public interface ModuleBuildTask extends BuildTask {
|
||||
@NotNull
|
||||
Module getModule();
|
||||
|
||||
boolean isIncludeDependentModules();
|
||||
|
||||
boolean isIncludeRuntimeDependencies();
|
||||
}
|
||||
|
||||
@@ -91,7 +91,15 @@ public abstract class ProjectTaskManager {
|
||||
|
||||
public abstract ProjectTask createAllModulesBuildTask(boolean isIncrementalBuild, Project project);
|
||||
|
||||
public abstract ProjectTask createModulesBuildTask(boolean isIncrementalBuild, Module... modules);
|
||||
public abstract ProjectTask createModulesBuildTask(Module module,
|
||||
boolean isIncrementalBuild,
|
||||
boolean includeDependentModules,
|
||||
boolean includeRuntimeDependencies);
|
||||
|
||||
public abstract ProjectTask createModulesBuildTask(Module[] modules,
|
||||
boolean isIncrementalBuild,
|
||||
boolean includeDependentModules,
|
||||
boolean includeRuntimeDependencies);
|
||||
|
||||
public abstract ProjectTask createArtifactsBuildTask(boolean isIncrementalBuild, Artifact... artifacts);
|
||||
|
||||
|
||||
@@ -164,7 +164,7 @@ public class CompileStepBeforeRun extends BeforeRunTaskProvider<CompileStepBefor
|
||||
runConfiguration.getClass().getName());
|
||||
}
|
||||
}
|
||||
projectTask = projectTaskManager.createModulesBuildTask(true, modules);
|
||||
projectTask = projectTaskManager.createModulesBuildTask(modules, true, true, true);
|
||||
}
|
||||
else {
|
||||
projectTask = projectTaskManager.createAllModulesBuildTask(true, myProject);
|
||||
|
||||
@@ -65,9 +65,11 @@ public class RefClassImpl extends RefJavaElementImpl implements RefClass {
|
||||
private Set<RefElement> myInTypeReferences;
|
||||
private Set<RefElement> myInstanceReferences;
|
||||
private List<RefJavaElement> myClassExporters;
|
||||
private RefModule myRefModule;
|
||||
|
||||
RefClassImpl(PsiClass psiClass, RefManager manager) {
|
||||
super(psiClass, manager);
|
||||
myRefModule = manager.getRefModule(ModuleUtilCore.findModuleForPsiElement(psiClass));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -226,6 +228,12 @@ public class RefClassImpl extends RefJavaElementImpl implements RefClass {
|
||||
return (PsiClass)super.getElement();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public RefModule getModule() {
|
||||
return myRefModule;
|
||||
}
|
||||
|
||||
private static boolean isSelfInheritor(PsiClass psiClass, ArrayList<PsiClass> visited) {
|
||||
if (visited.contains(psiClass)) return true;
|
||||
|
||||
|
||||
@@ -34,8 +34,10 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class RefImplicitConstructorImpl extends RefMethodImpl implements RefImplicitConstructor {
|
||||
|
||||
private final RefClass myOwnerClass;
|
||||
RefImplicitConstructorImpl(@NotNull RefClass ownerClass) {
|
||||
super(InspectionsBundle.message("inspection.reference.implicit.constructor.name", ownerClass.getName()), ownerClass);
|
||||
myOwnerClass = ownerClass;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -57,24 +57,20 @@ public class RefMethodImpl extends RefJavaElementImpl implements RefMethod {
|
||||
|
||||
private RefParameter[] myParameters;
|
||||
private String myReturnValueTemplate;
|
||||
protected final RefClass myOwnerClass;
|
||||
|
||||
RefMethodImpl(@NotNull RefClass ownerClass, PsiMethod method, RefManager manager) {
|
||||
super(method, manager);
|
||||
|
||||
((RefClassImpl)ownerClass).add(this);
|
||||
|
||||
myOwnerClass = ownerClass;
|
||||
}
|
||||
|
||||
// To be used only from RefImplicitConstructor.
|
||||
protected RefMethodImpl(@NotNull String name, @NotNull RefClass ownerClass) {
|
||||
super(name, ownerClass);
|
||||
myOwnerClass = ownerClass;
|
||||
((RefClassImpl)ownerClass).add(this);
|
||||
|
||||
addOutReference(getOwnerClass());
|
||||
((RefClassImpl)getOwnerClass()).addInReference(this);
|
||||
addOutReference(ownerClass);
|
||||
((RefClassImpl)ownerClass).addInReference(this);
|
||||
|
||||
setConstructor(true);
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import com.intellij.codeInspection.reference.*;
|
||||
import com.intellij.openapi.progress.EmptyProgressIndicator;
|
||||
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -246,7 +247,7 @@ public class SameParameterValueInspectionBase extends GlobalJavaBatchInspectionT
|
||||
PsiParameter parameter,
|
||||
String value) {
|
||||
final String name = parameter.getName();
|
||||
return manager.createProblemDescriptor(parameter,
|
||||
return manager.createProblemDescriptor(ObjectUtils.notNull(parameter.getNameIdentifier(), parameter),
|
||||
InspectionsBundle.message("inspection.same.parameter.problem.descriptor",
|
||||
"<code>" + name + "</code>",
|
||||
"<code>" + value + "</code>"),
|
||||
|
||||
@@ -401,12 +401,10 @@ public class DuplicatesFinder {
|
||||
final PsiType type1 = ((PsiNewExpression)pattern).getType();
|
||||
final PsiType type2 = ((PsiNewExpression)candidate).getType();
|
||||
if (type1 == null || type2 == null) return false;
|
||||
final PsiJavaCodeReferenceElement classReference1 = ((PsiNewExpression)pattern).getClassReference();
|
||||
final PsiJavaCodeReferenceElement classReference2 = ((PsiNewExpression)candidate).getClassReference();
|
||||
if (classReference1 != null && classReference2 != null) {
|
||||
final PsiElement resolved1 = classReference1.resolve();
|
||||
final PsiElement resolved2 = classReference2.resolve();
|
||||
if (!pattern.getManager().areElementsEquivalent(resolved1, resolved2)) return false;
|
||||
final PsiMethod constructor1 = ((PsiNewExpression)pattern).resolveConstructor();
|
||||
final PsiMethod constructor2 = ((PsiNewExpression)candidate).resolveConstructor();
|
||||
if (constructor1 != null && constructor2 != null) {
|
||||
if (!pattern.getManager().areElementsEquivalent(constructor1, constructor2)) return false;
|
||||
}
|
||||
else {
|
||||
if (!canTypesBeEquivalent(type1, type2)) return false;
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
*/
|
||||
package com.intellij.codeInsight.daemon.impl;
|
||||
|
||||
import com.intellij.openapi.util.Couple;
|
||||
import com.intellij.codeInsight.hints.filtering.Matcher;
|
||||
import com.intellij.codeInsight.hints.filtering.MatcherConstructor;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
@@ -26,22 +27,25 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static com.intellij.openapi.util.text.StringUtil.containsIgnoreCase;
|
||||
import static com.intellij.psi.CommonClassNames.JAVA_LANG_STRING;
|
||||
|
||||
public class ParameterNameHintsManager {
|
||||
private static final List<Couple<String>> COMMONLY_USED_PARAMETER_PAIR = ContainerUtil.newArrayList(
|
||||
Couple.of("begin", "end"),
|
||||
Couple.of("start", "end"),
|
||||
Couple.of("first", "last"),
|
||||
Couple.of("first", "second"),
|
||||
Couple.of("from", "to"),
|
||||
Couple.of("key", "value"),
|
||||
Couple.of("min", "max"),
|
||||
Couple.of("format", "arg")
|
||||
);
|
||||
|
||||
|
||||
private static List<Matcher> MATCHERS = Stream.of(
|
||||
"(begin*, end*)",
|
||||
"(start*, end*)",
|
||||
"(first*, last*)",
|
||||
"(first*, second*)",
|
||||
"(from*, to*)",
|
||||
"(min*, max*)",
|
||||
"(key, value)",
|
||||
"(format, arg)"
|
||||
).map((s) -> MatcherConstructor.INSTANCE.createMatcher(s))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
private static final Set<String> COMMON_METHOD_NAMES = ContainerUtil.newHashSet("set", "print", "println");
|
||||
|
||||
@NotNull
|
||||
@@ -173,7 +177,7 @@ public class ParameterNameHintsManager {
|
||||
|
||||
final int totalDescriptors = descriptors.size();
|
||||
if (totalDescriptors == 1 && shouldIgnoreSingleHint(parameters, descriptors)
|
||||
|| totalDescriptors == 2 && parameters.length == 2 && isParamPairToIgnore(descriptors.get(0), descriptors.get(1)))
|
||||
|| totalDescriptors == 2 && parameters.length == 2 && isParamPairToIgnore(descriptors))
|
||||
{
|
||||
return ContainerUtil.emptyList();
|
||||
}
|
||||
@@ -206,18 +210,13 @@ public class ParameterNameHintsManager {
|
||||
return new InlayInfo(paramName, callArgument.getTextRange().getStartOffset(), callArgument);
|
||||
}
|
||||
|
||||
private static boolean isParamPairToIgnore(InlayInfo first, InlayInfo second) {
|
||||
String firstParamName = first.getText();
|
||||
String secondParamName = second.getText();
|
||||
private static boolean isParamPairToIgnore(List<InlayInfo> descriptors) {
|
||||
List<String> params = descriptors
|
||||
.stream()
|
||||
.map((e) -> e.getText())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
for (Couple<String> knownPair : COMMONLY_USED_PARAMETER_PAIR) {
|
||||
if (containsIgnoreCase(firstParamName, knownPair.first)
|
||||
&& containsIgnoreCase(secondParamName, knownPair.second)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return MATCHERS.stream().anyMatch((e) -> e.isMatching("", params));
|
||||
}
|
||||
|
||||
private static boolean shouldInlineParameterName(@NotNull PsiExpression argument,
|
||||
|
||||
@@ -19,18 +19,16 @@ import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInspection.LambdaCanBeMethodReferenceInspection;
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.codeInspection.streamMigration.StreamApiMigrationInspection.InitializerUsageStatus;
|
||||
import com.intellij.codeInspection.streamMigration.StreamApiMigrationInspection.Operation;
|
||||
import com.intellij.codeInspection.streamMigration.StreamApiMigrationInspection.TerminalBlock;
|
||||
import com.intellij.codeInspection.streamMigration.StreamApiMigrationInspection.*;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.controlFlow.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.siyeh.ig.psiutils.ExpressionUtils;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
@@ -49,65 +47,61 @@ abstract class MigrateToStreamFix implements LocalQuickFix {
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
PsiElement element = descriptor.getPsiElement();
|
||||
if (element instanceof PsiForeachStatement) {
|
||||
PsiForeachStatement foreachStatement = (PsiForeachStatement)element;
|
||||
PsiStatement body = foreachStatement.getBody();
|
||||
final PsiExpression iteratedValue = foreachStatement.getIteratedValue();
|
||||
if (body != null && iteratedValue != null) {
|
||||
final PsiParameter parameter = foreachStatement.getIterationParameter();
|
||||
TerminalBlock tb = TerminalBlock.from(parameter, body);
|
||||
if (!FileModificationService.getInstance().preparePsiElementForWrite(foreachStatement)) return;
|
||||
PsiElement result = migrate(project, descriptor, foreachStatement, iteratedValue, body, tb);
|
||||
if(result != null) {
|
||||
simplifyAndFormat(project, result);
|
||||
}
|
||||
if (element instanceof PsiLoopStatement) {
|
||||
PsiLoopStatement loopStatement = (PsiLoopStatement)element;
|
||||
StreamSource source = StreamSource.tryCreate(loopStatement);
|
||||
PsiStatement body = loopStatement.getBody();
|
||||
if(body == null || source == null) return;
|
||||
TerminalBlock tb = TerminalBlock.from(source, body);
|
||||
if (!FileModificationService.getInstance().preparePsiElementForWrite(loopStatement)) return;
|
||||
PsiElement result = migrate(project, loopStatement, body, tb);
|
||||
if(result != null) {
|
||||
simplifyAndFormat(project, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract PsiElement migrate(@NotNull Project project,
|
||||
@NotNull ProblemDescriptor descriptor,
|
||||
@NotNull PsiForeachStatement foreachStatement,
|
||||
@NotNull PsiExpression iteratedValue,
|
||||
@NotNull PsiStatement body,
|
||||
@NotNull TerminalBlock tb);
|
||||
@NotNull PsiLoopStatement loopStatement,
|
||||
@NotNull PsiStatement body,
|
||||
@NotNull TerminalBlock tb);
|
||||
|
||||
static PsiElement replaceWithNumericAddition(@NotNull Project project,
|
||||
PsiForeachStatement foreachStatement,
|
||||
PsiLoopStatement loopStatement,
|
||||
PsiVariable var,
|
||||
StringBuilder builder,
|
||||
PsiType expressionType) {
|
||||
PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
|
||||
restoreComments(foreachStatement, foreachStatement.getBody());
|
||||
InitializerUsageStatus status = StreamApiMigrationInspection.getInitializerUsageStatus(var, foreachStatement);
|
||||
restoreComments(loopStatement, loopStatement.getBody());
|
||||
InitializerUsageStatus status = StreamApiMigrationInspection.getInitializerUsageStatus(var, loopStatement);
|
||||
if (status != InitializerUsageStatus.UNKNOWN) {
|
||||
PsiExpression initializer = var.getInitializer();
|
||||
if (ExpressionUtils.isZero(initializer)) {
|
||||
PsiType type = var.getType();
|
||||
String replacement = (type.equals(expressionType) ? "" : "(" + type.getCanonicalText() + ") ") + builder;
|
||||
return replaceInitializer(foreachStatement, var, initializer, replacement, status);
|
||||
return replaceInitializer(loopStatement, var, initializer, replacement, status);
|
||||
}
|
||||
}
|
||||
return foreachStatement.replace(elementFactory.createStatementFromText(var.getName() + "+=" + builder + ";", foreachStatement));
|
||||
return loopStatement.replace(elementFactory.createStatementFromText(var.getName() + "+=" + builder + ";", loopStatement));
|
||||
}
|
||||
|
||||
static PsiElement replaceInitializer(PsiForeachStatement foreachStatement,
|
||||
static PsiElement replaceInitializer(PsiLoopStatement loopStatement,
|
||||
PsiVariable var,
|
||||
PsiExpression initializer,
|
||||
String replacement,
|
||||
InitializerUsageStatus status) {
|
||||
Project project = foreachStatement.getProject();
|
||||
Project project = loopStatement.getProject();
|
||||
PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
|
||||
if(status == InitializerUsageStatus.DECLARED_JUST_BEFORE) {
|
||||
initializer.replace(elementFactory.createExpressionFromText(replacement, foreachStatement));
|
||||
removeLoop(foreachStatement);
|
||||
initializer.replace(elementFactory.createExpressionFromText(replacement, loopStatement));
|
||||
removeLoop(loopStatement);
|
||||
return var;
|
||||
} else {
|
||||
if(status == InitializerUsageStatus.AT_WANTED_PLACE_ONLY) {
|
||||
initializer.delete();
|
||||
}
|
||||
return
|
||||
foreachStatement.replace(elementFactory.createStatementFromText(var.getName() + " = " + replacement + ";", foreachStatement));
|
||||
loopStatement.replace(elementFactory.createStatementFromText(var.getName() + " = " + replacement + ";", loopStatement));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,34 +111,26 @@ abstract class MigrateToStreamFix implements LocalQuickFix {
|
||||
CodeStyleManager.getInstance(project).reformat(JavaCodeStyleManager.getInstance(project).shortenClassReferences(result));
|
||||
}
|
||||
|
||||
static void restoreComments(PsiForeachStatement foreachStatement, PsiStatement body) {
|
||||
final PsiElement parent = foreachStatement.getParent();
|
||||
static void restoreComments(PsiLoopStatement loopStatement, PsiStatement body) {
|
||||
final PsiElement parent = loopStatement.getParent();
|
||||
for (PsiElement comment : PsiTreeUtil.findChildrenOfType(body, PsiComment.class)) {
|
||||
parent.addBefore(comment, foreachStatement);
|
||||
parent.addBefore(comment, loopStatement);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static StringBuilder generateStream(PsiExpression iteratedValue, @Nullable Operation lastOperation) {
|
||||
return generateStream(iteratedValue, lastOperation, false);
|
||||
static StringBuilder generateStream(@NotNull Operation lastOperation) {
|
||||
return generateStream(lastOperation, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static StringBuilder generateStream(PsiExpression iteratedValue, @Nullable Operation lastOperation, boolean noStreamForEmpty) {
|
||||
static StringBuilder generateStream(@NotNull Operation lastOperation, boolean noStreamForEmpty) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
final PsiType iteratedValueType = iteratedValue.getType();
|
||||
if (iteratedValueType instanceof PsiArrayType) {
|
||||
buffer.append("java.util.Arrays.stream(").append(iteratedValue.getText()).append(")");
|
||||
if(noStreamForEmpty && lastOperation instanceof CollectionStream) {
|
||||
return buffer.append(lastOperation.getExpression().getText());
|
||||
}
|
||||
else {
|
||||
buffer.append(getIteratedValueText(iteratedValue));
|
||||
if (!noStreamForEmpty || lastOperation != null) {
|
||||
buffer.append(".stream()");
|
||||
}
|
||||
}
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(iteratedValue.getProject());
|
||||
List<String> replacements =
|
||||
StreamEx.iterate(lastOperation, Objects::nonNull, Operation::getPreviousOp).map(op -> op.createReplacement(factory)).toList();
|
||||
StreamEx.iterate(lastOperation, Objects::nonNull, Operation::getPreviousOp).map(Operation::createReplacement).toList();
|
||||
for(ListIterator<String> it = replacements.listIterator(replacements.size()); it.hasPrevious(); ) {
|
||||
buffer.append(it.previous());
|
||||
}
|
||||
@@ -158,7 +144,7 @@ abstract class MigrateToStreamFix implements LocalQuickFix {
|
||||
iteratedValue instanceof PsiParenthesizedExpression ? iteratedValue.getText() : "(" + iteratedValue.getText() + ")";
|
||||
}
|
||||
|
||||
static void removeLoop(@NotNull PsiForeachStatement statement) {
|
||||
static void removeLoop(@NotNull PsiLoopStatement statement) {
|
||||
PsiElement parent = statement.getParent();
|
||||
if (parent instanceof PsiLabeledStatement) {
|
||||
parent.delete();
|
||||
@@ -167,4 +153,16 @@ abstract class MigrateToStreamFix implements LocalQuickFix {
|
||||
statement.delete();
|
||||
}
|
||||
}
|
||||
|
||||
static boolean isReachable(PsiReturnStatement target) {
|
||||
ControlFlow flow;
|
||||
try {
|
||||
flow = ControlFlowFactory.getInstance(target.getProject())
|
||||
.getControlFlow(target.getParent(), LocalsOrMyInstanceFieldsControlFlowPolicy.getInstance());
|
||||
}
|
||||
catch (AnalysisCanceledException e) {
|
||||
return true;
|
||||
}
|
||||
return ControlFlowUtil.isInstructionReachable(flow, flow.getStartOffset(target), 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
package com.intellij.codeInspection.streamMigration;
|
||||
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.codeInspection.streamMigration.StreamApiMigrationInspection.InitializerUsageStatus;
|
||||
import com.intellij.codeInspection.streamMigration.StreamApiMigrationInspection.MapOp;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -58,42 +58,41 @@ class ReplaceWithCollectFix extends MigrateToStreamFix {
|
||||
|
||||
@Override
|
||||
PsiElement migrate(@NotNull Project project,
|
||||
@NotNull ProblemDescriptor descriptor,
|
||||
@NotNull PsiForeachStatement foreachStatement,
|
||||
@NotNull PsiExpression iteratedValue,
|
||||
@NotNull PsiStatement body,
|
||||
@NotNull StreamApiMigrationInspection.TerminalBlock tb) {
|
||||
@NotNull PsiLoopStatement loopStatement,
|
||||
@NotNull PsiStatement body,
|
||||
@NotNull StreamApiMigrationInspection.TerminalBlock tb) {
|
||||
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
|
||||
final PsiType iteratedValueType = iteratedValue.getType();
|
||||
final PsiMethodCallExpression methodCallExpression = tb.getSingleMethodCall();
|
||||
|
||||
if (methodCallExpression == null) return null;
|
||||
|
||||
restoreComments(foreachStatement, body);
|
||||
if (!tb.hasOperations() && StreamApiMigrationInspection.isAddAllCall(tb)) {
|
||||
restoreComments(loopStatement, body);
|
||||
if (!tb.hasOperations() && StreamApiMigrationInspection.isAddAllCall(tb) && loopStatement instanceof PsiForeachStatement) {
|
||||
PsiExpression iteratedValue = ((PsiForeachStatement)loopStatement).getIteratedValue();
|
||||
if (iteratedValue == null) return null;
|
||||
final PsiType iteratedValueType = iteratedValue.getType();
|
||||
final PsiExpression qualifierExpression = methodCallExpression.getMethodExpression().getQualifierExpression();
|
||||
final String qualifierText = qualifierExpression != null ? qualifierExpression.getText() : "";
|
||||
final String collectionText =
|
||||
iteratedValueType instanceof PsiArrayType ? "java.util.Arrays.asList(" + iteratedValue.getText() + ")" :
|
||||
getIteratedValueText(iteratedValue);
|
||||
final String callText = StringUtil.getQualifiedName(qualifierText, "addAll(" + collectionText + ");");
|
||||
return foreachStatement.replace(elementFactory.createStatementFromText(callText, foreachStatement));
|
||||
return loopStatement.replace(elementFactory.createStatementFromText(callText, loopStatement));
|
||||
}
|
||||
PsiExpression itemToAdd = methodCallExpression.getArgumentList().getExpressions()[0];
|
||||
PsiType addedType = getAddedElementType(methodCallExpression);
|
||||
if (addedType == null) addedType = itemToAdd.getType();
|
||||
final StringBuilder builder =
|
||||
generateStream(iteratedValue, new StreamApiMigrationInspection.MapOp(tb.getLastOperation(), itemToAdd, tb.getVariable(), addedType));
|
||||
StringBuilder builder = generateStream(new MapOp(tb.getLastOperation(), itemToAdd, tb.getVariable(), addedType));
|
||||
|
||||
final PsiExpression qualifierExpression = methodCallExpression.getMethodExpression().getQualifierExpression();
|
||||
final PsiLocalVariable variable = StreamApiMigrationInspection.extractCollectionVariable(qualifierExpression);
|
||||
if (variable != null) {
|
||||
InitializerUsageStatus status = StreamApiMigrationInspection.getInitializerUsageStatus(variable, foreachStatement);
|
||||
InitializerUsageStatus status = StreamApiMigrationInspection.getInitializerUsageStatus(variable, loopStatement);
|
||||
if(status != InitializerUsageStatus.UNKNOWN) {
|
||||
PsiExpression initializer = variable.getInitializer();
|
||||
LOG.assertTrue(initializer != null);
|
||||
PsiMethodCallExpression toArrayExpression =
|
||||
StreamApiMigrationInspection.extractToArrayExpression(foreachStatement, methodCallExpression);
|
||||
StreamApiMigrationInspection.extractToArrayExpression(loopStatement, methodCallExpression);
|
||||
if(toArrayExpression != null) {
|
||||
PsiType type = initializer.getType();
|
||||
if(type instanceof PsiClassType) {
|
||||
@@ -113,7 +112,7 @@ class ReplaceWithCollectFix extends MigrateToStreamFix {
|
||||
}
|
||||
PsiElement result =
|
||||
toArrayExpression.replace(elementFactory.createExpressionFromText(builder.toString(), toArrayExpression));
|
||||
removeLoop(foreachStatement);
|
||||
removeLoop(loopStatement);
|
||||
if(status != InitializerUsageStatus.AT_WANTED_PLACE) {
|
||||
variable.delete();
|
||||
}
|
||||
@@ -121,7 +120,7 @@ class ReplaceWithCollectFix extends MigrateToStreamFix {
|
||||
}
|
||||
}
|
||||
}
|
||||
PsiElement nextStatement = PsiTreeUtil.skipSiblingsForward(foreachStatement, PsiComment.class, PsiWhiteSpace.class);
|
||||
PsiElement nextStatement = PsiTreeUtil.skipSiblingsForward(loopStatement, PsiComment.class, PsiWhiteSpace.class);
|
||||
String comparatorText = StreamApiMigrationInspection.tryExtractSortComparatorText(nextStatement, variable);
|
||||
if(comparatorText != null) {
|
||||
builder.append(".sorted(").append(comparatorText).append(")");
|
||||
@@ -130,7 +129,7 @@ class ReplaceWithCollectFix extends MigrateToStreamFix {
|
||||
String callText = builder.append(".collect(java.util.stream.Collectors.")
|
||||
.append(createInitializerReplacementText(qualifierExpression.getType(), initializer))
|
||||
.append(")").toString();
|
||||
return replaceInitializer(foreachStatement, variable, initializer, callText, status);
|
||||
return replaceInitializer(loopStatement, variable, initializer, callText, status);
|
||||
}
|
||||
}
|
||||
final String qualifierText = qualifierExpression != null ? qualifierExpression.getText() + "." : "";
|
||||
@@ -147,7 +146,7 @@ class ReplaceWithCollectFix extends MigrateToStreamFix {
|
||||
elementFactory.createExpressionFromText(qualifierText + "add(" + varName + ")", qualifierExpression);
|
||||
final String callText =
|
||||
builder.append(".forEach(").append(varName).append("->").append(forEachBody.getText()).append(");").toString();
|
||||
return foreachStatement.replace(elementFactory.createStatementFromText(callText, foreachStatement));
|
||||
return loopStatement.replace(elementFactory.createStatementFromText(callText, loopStatement));
|
||||
}
|
||||
|
||||
private static String createInitializerReplacementText(PsiType varType, PsiExpression initializer) {
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.intellij.codeInspection.streamMigration;
|
||||
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -33,18 +32,15 @@ class ReplaceWithCountFix extends MigrateToStreamFix {
|
||||
|
||||
@Override
|
||||
PsiElement migrate(@NotNull Project project,
|
||||
@NotNull ProblemDescriptor descriptor,
|
||||
@NotNull PsiForeachStatement foreachStatement,
|
||||
@NotNull PsiExpression iteratedValue,
|
||||
@NotNull PsiStatement body,
|
||||
@NotNull StreamApiMigrationInspection.TerminalBlock tb) {
|
||||
@NotNull PsiLoopStatement loopStatement,
|
||||
@NotNull PsiStatement body,
|
||||
@NotNull StreamApiMigrationInspection.TerminalBlock tb) {
|
||||
PsiExpression operand = StreamApiMigrationInspection.extractIncrementedLValue(tb.getSingleExpression(PsiExpression.class));
|
||||
if (!(operand instanceof PsiReferenceExpression)) return null;
|
||||
PsiElement element = ((PsiReferenceExpression)operand).resolve();
|
||||
if (!(element instanceof PsiLocalVariable)) return null;
|
||||
PsiLocalVariable var = (PsiLocalVariable)element;
|
||||
final StringBuilder builder = generateStream(iteratedValue, tb.getLastOperation());
|
||||
builder.append(".count()");
|
||||
return replaceWithNumericAddition(project, foreachStatement, var, builder, PsiType.LONG);
|
||||
StringBuilder builder = generateStream(tb.getLastOperation()).append(".count()");
|
||||
return replaceWithNumericAddition(project, loopStatement, var, builder, PsiType.LONG);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
package com.intellij.codeInspection.streamMigration;
|
||||
|
||||
import com.intellij.codeInsight.PsiEquivalenceUtil;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.codeInspection.streamMigration.StreamApiMigrationInspection.InitializerUsageStatus;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.siyeh.ig.psiutils.ExpressionUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -36,28 +36,29 @@ class ReplaceWithFindFirstFix extends MigrateToStreamFix {
|
||||
|
||||
@Override
|
||||
PsiElement migrate(@NotNull Project project,
|
||||
@NotNull ProblemDescriptor descriptor,
|
||||
@NotNull PsiForeachStatement foreachStatement,
|
||||
@NotNull PsiExpression iteratedValue,
|
||||
@NotNull PsiStatement body,
|
||||
@NotNull StreamApiMigrationInspection.TerminalBlock tb) {
|
||||
@NotNull PsiLoopStatement loopStatement,
|
||||
@NotNull PsiStatement body,
|
||||
@NotNull StreamApiMigrationInspection.TerminalBlock tb) {
|
||||
PsiStatement statement = tb.getSingleStatement();
|
||||
PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
|
||||
String stream = generateStream(iteratedValue, tb.getLastOperation()).append(".findFirst()").toString();
|
||||
StringBuilder builder = generateStream(tb.getLastOperation());
|
||||
String stream = builder.append(".findFirst()").toString();
|
||||
if (statement instanceof PsiReturnStatement) {
|
||||
PsiReturnStatement returnStatement = (PsiReturnStatement)statement;
|
||||
PsiExpression value = returnStatement.getReturnValue();
|
||||
if (value == null) return null;
|
||||
PsiReturnStatement nextReturnStatement = StreamApiMigrationInspection.getNextReturnStatement(foreachStatement);
|
||||
PsiReturnStatement nextReturnStatement = StreamApiMigrationInspection.getNextReturnStatement(loopStatement);
|
||||
if (nextReturnStatement == null) return null;
|
||||
PsiExpression orElseExpression = nextReturnStatement.getReturnValue();
|
||||
if (!ExpressionUtils.isSimpleExpression(orElseExpression)) return null;
|
||||
stream = generateOptionalUnwrap(stream, tb, value, orElseExpression, null);
|
||||
restoreComments(foreachStatement, body);
|
||||
if (nextReturnStatement.getParent() == foreachStatement.getParent()) {
|
||||
restoreComments(loopStatement, body);
|
||||
boolean sibling = nextReturnStatement.getParent() == loopStatement.getParent();
|
||||
PsiElement replacement = loopStatement.replace(elementFactory.createStatementFromText("return " + stream + ";", loopStatement));
|
||||
if(sibling || !isReachable(nextReturnStatement)) {
|
||||
nextReturnStatement.delete();
|
||||
}
|
||||
return foreachStatement.replace(elementFactory.createStatementFromText("return " + stream + ";", foreachStatement));
|
||||
return replacement;
|
||||
}
|
||||
else {
|
||||
PsiStatement[] statements = tb.getStatements();
|
||||
@@ -66,9 +67,9 @@ class ReplaceWithFindFirstFix extends MigrateToStreamFix {
|
||||
if (assignment == null) {
|
||||
if(!(statements[0] instanceof PsiExpressionStatement)) return null;
|
||||
PsiExpression expression = ((PsiExpressionStatement)statements[0]).getExpression();
|
||||
restoreComments(foreachStatement, body);
|
||||
return foreachStatement.replace(elementFactory.createStatementFromText(
|
||||
stream + ".ifPresent(" + LambdaUtil.createLambda(tb.getVariable(), expression) + ");", foreachStatement));
|
||||
restoreComments(loopStatement, body);
|
||||
return loopStatement.replace(elementFactory.createStatementFromText(
|
||||
stream + ".ifPresent(" + LambdaUtil.createLambda(tb.getVariable(), expression) + ");", loopStatement));
|
||||
}
|
||||
PsiExpression lValue = assignment.getLExpression();
|
||||
if (!(lValue instanceof PsiReferenceExpression)) return null;
|
||||
@@ -77,17 +78,28 @@ class ReplaceWithFindFirstFix extends MigrateToStreamFix {
|
||||
PsiVariable var = (PsiVariable)element;
|
||||
PsiExpression value = assignment.getRExpression();
|
||||
if (value == null) return null;
|
||||
restoreComments(foreachStatement, body);
|
||||
InitializerUsageStatus status = StreamApiMigrationInspection.getInitializerUsageStatus(var, foreachStatement);
|
||||
restoreComments(loopStatement, body);
|
||||
InitializerUsageStatus status = StreamApiMigrationInspection.getInitializerUsageStatus(var, loopStatement);
|
||||
if (status != InitializerUsageStatus.UNKNOWN) {
|
||||
PsiExpression initializer = var.getInitializer();
|
||||
if (initializer != null) {
|
||||
String replacementText = generateOptionalUnwrap(stream, tb, value, initializer, var.getType());
|
||||
return replaceInitializer(foreachStatement, var, initializer, replacementText, status);
|
||||
return replaceInitializer(loopStatement, var, initializer, replacementText, status);
|
||||
}
|
||||
}
|
||||
return foreachStatement.replace(elementFactory.createStatementFromText(
|
||||
var.getName() + " = " + generateOptionalUnwrap(stream, tb, value, lValue, var.getType()) + ";", foreachStatement));
|
||||
PsiAssignmentExpression previousAssignment =
|
||||
ExpressionUtils.getAssignment(PsiTreeUtil.skipSiblingsBackward(loopStatement, PsiWhiteSpace.class, PsiComment.class));
|
||||
if(previousAssignment != null) {
|
||||
PsiExpression prevRValue = previousAssignment.getRExpression();
|
||||
PsiExpression prevLValue = previousAssignment.getLExpression();
|
||||
if(prevRValue != null && prevLValue instanceof PsiReferenceExpression && ((PsiReferenceExpression)prevLValue).resolve() == var) {
|
||||
previousAssignment.delete();
|
||||
return loopStatement.replace(elementFactory.createStatementFromText(
|
||||
var.getName() + " = " + generateOptionalUnwrap(stream, tb, value, prevRValue, var.getType()) + ";", loopStatement));
|
||||
}
|
||||
}
|
||||
return loopStatement.replace(elementFactory.createStatementFromText(
|
||||
var.getName() + " = " + generateOptionalUnwrap(stream, tb, value, lValue, var.getType()) + ";", loopStatement));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.intellij.codeInspection.streamMigration;
|
||||
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
@@ -41,24 +40,22 @@ class ReplaceWithForeachCallFix extends MigrateToStreamFix {
|
||||
|
||||
@Override
|
||||
PsiElement migrate(@NotNull Project project,
|
||||
@NotNull ProblemDescriptor descriptor,
|
||||
@NotNull PsiForeachStatement foreachStatement,
|
||||
@NotNull PsiExpression iteratedValue,
|
||||
@NotNull PsiStatement body,
|
||||
@NotNull StreamApiMigrationInspection.TerminalBlock tb) {
|
||||
restoreComments(foreachStatement, body);
|
||||
@NotNull PsiLoopStatement loopStatement,
|
||||
@NotNull PsiStatement body,
|
||||
@NotNull StreamApiMigrationInspection.TerminalBlock tb) {
|
||||
restoreComments(loopStatement, body);
|
||||
|
||||
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
|
||||
|
||||
StringBuilder buffer = generateStream(iteratedValue, tb.getLastOperation(), true);
|
||||
StringBuilder buffer = generateStream(tb.getLastOperation(), true);
|
||||
PsiElement block = tb.convertToElement(elementFactory);
|
||||
|
||||
buffer.append(".").append(myForEachMethodName).append("(");
|
||||
|
||||
final String functionalExpressionText = tb.getVariable().getName() + " -> " + wrapInBlock(block);
|
||||
PsiExpressionStatement callStatement = (PsiExpressionStatement)elementFactory
|
||||
.createStatementFromText(buffer.toString() + functionalExpressionText + ");", foreachStatement);
|
||||
callStatement = (PsiExpressionStatement)foreachStatement.replace(callStatement);
|
||||
.createStatementFromText(buffer.toString() + functionalExpressionText + ");", loopStatement);
|
||||
callStatement = (PsiExpressionStatement)loopStatement.replace(callStatement);
|
||||
|
||||
final PsiExpressionList argumentList = ((PsiCallExpression)callStatement.getExpression()).getArgumentList();
|
||||
LOG.assertTrue(argumentList != null, callStatement.getText());
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.intellij.codeInspection.streamMigration;
|
||||
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.codeInspection.streamMigration.StreamApiMigrationInspection.InitializerUsageStatus;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -46,74 +45,78 @@ class ReplaceWithMatchFix extends MigrateToStreamFix {
|
||||
|
||||
@Override
|
||||
PsiElement migrate(@NotNull Project project,
|
||||
@NotNull ProblemDescriptor descriptor,
|
||||
@NotNull PsiForeachStatement foreachStatement,
|
||||
@NotNull PsiExpression iteratedValue,
|
||||
@NotNull PsiStatement body,
|
||||
@NotNull StreamApiMigrationInspection.TerminalBlock tb) {
|
||||
@NotNull PsiLoopStatement loopStatement,
|
||||
@NotNull PsiStatement body,
|
||||
@NotNull StreamApiMigrationInspection.TerminalBlock tb) {
|
||||
PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
|
||||
StringBuilder builder = generateStream(tb.getLastOperation());
|
||||
if(tb.getSingleStatement() instanceof PsiReturnStatement) {
|
||||
PsiReturnStatement returnStatement = (PsiReturnStatement)tb.getSingleStatement();
|
||||
PsiExpression value = returnStatement.getReturnValue();
|
||||
if (ExpressionUtils.isLiteral(value, Boolean.TRUE) || ExpressionUtils.isLiteral(value, Boolean.FALSE)) {
|
||||
boolean foundResult = (boolean)((PsiLiteralExpression)value).getValue();
|
||||
PsiReturnStatement nextReturnStatement = StreamApiMigrationInspection.getNextReturnStatement(foreachStatement);
|
||||
PsiReturnStatement nextReturnStatement = StreamApiMigrationInspection.getNextReturnStatement(loopStatement);
|
||||
if (nextReturnStatement != null) {
|
||||
PsiExpression returnValue = nextReturnStatement.getReturnValue();
|
||||
if(returnValue == null) return null;
|
||||
String methodName = foundResult ? "anyMatch" : "noneMatch";
|
||||
String streamText = generateStream(iteratedValue, tb.getLastOperation()).toString();
|
||||
streamText = addTerminalOperation(streamText, methodName, foreachStatement, tb);
|
||||
restoreComments(foreachStatement, body);
|
||||
if (nextReturnStatement.getParent() == foreachStatement.getParent()) {
|
||||
String streamText = addTerminalOperation(builder.toString(), methodName, loopStatement, tb);
|
||||
restoreComments(loopStatement, body);
|
||||
if (nextReturnStatement.getParent() == loopStatement.getParent()) {
|
||||
if(!ExpressionUtils.isLiteral(returnValue, !foundResult)) {
|
||||
streamText+= (foundResult ? "||" : "&&") + ParenthesesUtils.getText(returnValue, ParenthesesUtils.AND_PRECEDENCE);
|
||||
}
|
||||
removeLoop(foreachStatement);
|
||||
removeLoop(loopStatement);
|
||||
return returnValue.replace(elementFactory.createExpressionFromText(streamText, nextReturnStatement));
|
||||
}
|
||||
return foreachStatement.replace(elementFactory.createStatementFromText("return " + streamText + ";", foreachStatement));
|
||||
PsiElement result = loopStatement.replace(elementFactory.createStatementFromText("return " + streamText + ";", loopStatement));
|
||||
if(!isReachable(nextReturnStatement)) {
|
||||
nextReturnStatement.delete();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
PsiStatement[] statements = tb.getStatements();
|
||||
if (!(statements.length == 1 || (statements.length == 2 && ControlFlowUtils.statementBreaksLoop(statements[1], foreachStatement)))) {
|
||||
if (!(statements.length == 1 || (statements.length == 2 && ControlFlowUtils.statementBreaksLoop(statements[1], loopStatement)))) {
|
||||
return null;
|
||||
}
|
||||
restoreComments(foreachStatement, body);
|
||||
String streamText = generateStream(iteratedValue, tb.getLastOperation()).toString();
|
||||
streamText = addTerminalOperation(streamText, "anyMatch", foreachStatement, tb);
|
||||
restoreComments(loopStatement, body);
|
||||
String streamText = addTerminalOperation(builder.toString(), "anyMatch", loopStatement, tb);
|
||||
PsiStatement statement = statements[0];
|
||||
PsiAssignmentExpression assignment = ExpressionUtils.getAssignment(statement);
|
||||
if(assignment != null) {
|
||||
PsiExpression lValue = assignment.getLExpression();
|
||||
PsiExpression rValue = assignment.getRExpression();
|
||||
if (!(lValue instanceof PsiReferenceExpression) || rValue == null) return null;
|
||||
PsiElement maybeVar = ((PsiReferenceExpression)lValue).resolve();
|
||||
if(maybeVar instanceof PsiVariable) {
|
||||
// Simplify single assignments like this:
|
||||
// boolean flag = false;
|
||||
// for(....) if(...) {flag = true; break;}
|
||||
PsiVariable var = (PsiVariable)maybeVar;
|
||||
PsiExpression initializer = var.getInitializer();
|
||||
InitializerUsageStatus status = StreamApiMigrationInspection.getInitializerUsageStatus(var, foreachStatement);
|
||||
if(initializer != null && status != InitializerUsageStatus.UNKNOWN) {
|
||||
String replacement;
|
||||
if(ExpressionUtils.isLiteral(initializer, Boolean.FALSE) &&
|
||||
ExpressionUtils.isLiteral(rValue, Boolean.TRUE)) {
|
||||
replacement = streamText;
|
||||
} else if(ExpressionUtils.isLiteral(initializer, Boolean.TRUE) &&
|
||||
ExpressionUtils.isLiteral(rValue, Boolean.FALSE)) {
|
||||
replacement = "!"+streamText;
|
||||
} else {
|
||||
replacement = streamText + "?" + rValue.getText() + ":" + initializer.getText();
|
||||
if ((lValue instanceof PsiReferenceExpression) && rValue != null) {
|
||||
PsiElement maybeVar = ((PsiReferenceExpression)lValue).resolve();
|
||||
if (maybeVar instanceof PsiVariable) {
|
||||
// Simplify single assignments like this:
|
||||
// boolean flag = false;
|
||||
// for(....) if(...) {flag = true; break;}
|
||||
PsiVariable var = (PsiVariable)maybeVar;
|
||||
PsiExpression initializer = var.getInitializer();
|
||||
InitializerUsageStatus status = StreamApiMigrationInspection.getInitializerUsageStatus(var, loopStatement);
|
||||
if (initializer != null && status != InitializerUsageStatus.UNKNOWN) {
|
||||
String replacement;
|
||||
if (ExpressionUtils.isLiteral(initializer, Boolean.FALSE) &&
|
||||
ExpressionUtils.isLiteral(rValue, Boolean.TRUE)) {
|
||||
replacement = streamText;
|
||||
}
|
||||
else if (ExpressionUtils.isLiteral(initializer, Boolean.TRUE) &&
|
||||
ExpressionUtils.isLiteral(rValue, Boolean.FALSE)) {
|
||||
replacement = "!" + streamText;
|
||||
}
|
||||
else {
|
||||
replacement = streamText + "?" + rValue.getText() + ":" + initializer.getText();
|
||||
}
|
||||
return replaceInitializer(loopStatement, var, initializer, replacement, status);
|
||||
}
|
||||
return replaceInitializer(foreachStatement, var, initializer, replacement, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
String replacement = "if(" + streamText + "){" + statement.getText() + "}";
|
||||
return foreachStatement.replace(elementFactory.createStatementFromText(replacement, foreachStatement));
|
||||
return loopStatement.replace(elementFactory.createStatementFromText(replacement, loopStatement));
|
||||
}
|
||||
|
||||
private static String addTerminalOperation(String origStream, String methodName, @NotNull PsiElement contextElement,
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package com.intellij.codeInspection.streamMigration;
|
||||
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.codeInspection.streamMigration.StreamApiMigrationInspection.MapOp;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -33,11 +33,9 @@ class ReplaceWithSumFix extends MigrateToStreamFix {
|
||||
|
||||
@Override
|
||||
PsiElement migrate(@NotNull Project project,
|
||||
@NotNull ProblemDescriptor descriptor,
|
||||
@NotNull PsiForeachStatement foreachStatement,
|
||||
@NotNull PsiExpression iteratedValue,
|
||||
@NotNull PsiStatement body,
|
||||
@NotNull StreamApiMigrationInspection.TerminalBlock tb) {
|
||||
@NotNull PsiLoopStatement loopStatement,
|
||||
@NotNull PsiStatement body,
|
||||
@NotNull StreamApiMigrationInspection.TerminalBlock tb) {
|
||||
PsiAssignmentExpression assignment = tb.getSingleExpression(PsiAssignmentExpression.class);
|
||||
if (assignment == null) return null;
|
||||
PsiVariable var = StreamApiMigrationInspection.extractAccumulator(assignment);
|
||||
@@ -50,9 +48,8 @@ class ReplaceWithSumFix extends MigrateToStreamFix {
|
||||
if (!type.equals(PsiType.DOUBLE) && !type.equals(PsiType.LONG)) {
|
||||
type = PsiType.INT;
|
||||
}
|
||||
final StringBuilder builder =
|
||||
generateStream(iteratedValue, new StreamApiMigrationInspection.MapOp(tb.getLastOperation(), addend, tb.getVariable(), type));
|
||||
StringBuilder builder = generateStream(new MapOp(tb.getLastOperation(), addend, tb.getVariable(), type));
|
||||
builder.append(".sum()");
|
||||
return replaceWithNumericAddition(project, foreachStatement, var, builder, type);
|
||||
return replaceWithNumericAddition(project, loopStatement, var, builder, type);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import com.intellij.psi.controlFlow.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
@@ -43,6 +44,7 @@ import com.intellij.util.containers.IntArrayList;
|
||||
import com.siyeh.ig.psiutils.BoolUtils;
|
||||
import com.siyeh.ig.psiutils.ControlFlowUtils;
|
||||
import com.siyeh.ig.psiutils.ExpressionUtils;
|
||||
import com.siyeh.ig.psiutils.ParenthesesUtils;
|
||||
import one.util.streamex.EntryStream;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
@@ -123,7 +125,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
}
|
||||
|
||||
static boolean isReferencedInOperations(PsiElement element, TerminalBlock tb) {
|
||||
return ReferencesSearch.search(element, new LocalSearchScope(tb.intermediateExpressions().toArray(PsiElement[]::new)))
|
||||
return ReferencesSearch.search(element, new LocalSearchScope(tb.intermediateAndSourceExpressions().toArray(PsiElement[]::new)))
|
||||
.findFirst() != null;
|
||||
}
|
||||
|
||||
@@ -350,7 +352,10 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
return dependsOnCollection[0];
|
||||
}
|
||||
|
||||
private static boolean isTrivial(PsiStatement body, PsiParameter parameter) {
|
||||
@Contract("_, null -> false")
|
||||
private static boolean isTrivial(PsiStatement body, PsiLoopStatement loopStatement) {
|
||||
if(!(loopStatement instanceof PsiForeachStatement)) return false;
|
||||
PsiParameter parameter = ((PsiForeachStatement)loopStatement).getIterationParameter();
|
||||
//method reference
|
||||
final PsiExpression candidate = new LambdaCanBeMethodReferenceInspection()
|
||||
.canBeMethodReferenceProblem(body instanceof PsiBlockStatement ? ((PsiBlockStatement)body).getCodeBlock() : body,
|
||||
@@ -385,6 +390,27 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
return consumerClass != null ? psiFacade.getElementFactory().createType(consumerClass, variable.getType()) : null;
|
||||
}
|
||||
|
||||
static boolean isVariableSuitableForStream(PsiVariable variable, PsiStatement statement) {
|
||||
PsiElement declaration = variable.getParent();
|
||||
// For-loop initializer is not effectively final, but suitable for stream conversion
|
||||
if(declaration instanceof PsiDeclarationStatement) {
|
||||
PsiElement grandParent = declaration.getParent();
|
||||
if (grandParent instanceof PsiForStatement) {
|
||||
PsiForStatement forStatement = (PsiForStatement)grandParent;
|
||||
if (forStatement.getInitialization() == declaration) {
|
||||
PsiStatement body = forStatement.getBody();
|
||||
if(body != null && PsiTreeUtil.isAncestor(statement, body, false)) {
|
||||
return ReferencesSearch.search(variable, new LocalSearchScope(body)).forEach(ref -> {
|
||||
PsiElement element = ref.getElement();
|
||||
return !(element instanceof PsiExpression) || !PsiUtil.isAccessedForWriting((PsiExpression)element);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return HighlightControlFlowUtil.isEffectivelyFinal(variable, statement, null);
|
||||
}
|
||||
|
||||
@Contract("null -> null")
|
||||
static PsiLocalVariable extractCollectionVariable(PsiExpression qualifierExpression) {
|
||||
if (qualifierExpression instanceof PsiReferenceExpression) {
|
||||
@@ -465,26 +491,22 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
@Override
|
||||
public void visitForeachStatement(PsiForeachStatement statement) {
|
||||
super.visitForeachStatement(statement);
|
||||
final PsiExpression iteratedValue = statement.getIteratedValue();
|
||||
processLoop(statement);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitForStatement(PsiForStatement statement) {
|
||||
super.visitForStatement(statement);
|
||||
processLoop(statement);
|
||||
}
|
||||
|
||||
void processLoop(PsiLoopStatement statement) {
|
||||
final PsiStatement body = statement.getBody();
|
||||
if (iteratedValue == null || body == null) return;
|
||||
|
||||
final PsiType iteratedValueType = iteratedValue.getType();
|
||||
final PsiClass iteratorClass = PsiUtil.resolveClassInClassTypeOnly(iteratedValueType);
|
||||
PsiClass collectionClass = null;
|
||||
final boolean isArray;
|
||||
if(iteratedValueType instanceof PsiArrayType) {
|
||||
if(!isSupported(((PsiArrayType)iteratedValueType).getComponentType())) return;
|
||||
isArray = true;
|
||||
} else {
|
||||
collectionClass = JavaPsiFacade.getInstance(body.getProject()).findClass(CommonClassNames.JAVA_UTIL_COLLECTION, statement.getResolveScope());
|
||||
if (collectionClass != null && InheritanceUtil.isInheritorOrSelf(iteratorClass, collectionClass, true)) {
|
||||
isArray = false;
|
||||
} else return;
|
||||
}
|
||||
if(body == null) return;
|
||||
StreamSource source = StreamSource.tryCreate(statement);
|
||||
if(source == null) return;
|
||||
if (!ExceptionUtil.getThrownCheckedExceptions(body).isEmpty()) return;
|
||||
|
||||
TerminalBlock tb = TerminalBlock.from(statement.getIterationParameter(), body);
|
||||
TerminalBlock tb = TerminalBlock.from(source, body);
|
||||
if(tb.isEmpty()) return;
|
||||
|
||||
final ControlFlow controlFlow;
|
||||
@@ -502,7 +524,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
int startOffset = controlFlow.getStartOffset(body);
|
||||
int endOffset = controlFlow.getEndOffset(body);
|
||||
final List<PsiVariable> nonFinalVariables = StreamEx.of(ControlFlowUtil.getUsedVariables(controlFlow, startOffset, endOffset))
|
||||
.remove(variable -> HighlightControlFlowUtil.isEffectivelyFinal(variable, body, null)).toList();
|
||||
.remove(variable -> isVariableSuitableForStream(variable, statement)).toList();
|
||||
|
||||
if (exitPoints.isEmpty()) {
|
||||
if(getIncrementedVariable(tb, nonFinalVariables) != null) {
|
||||
@@ -514,8 +536,8 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
if(!nonFinalVariables.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if ((isArray || !isRawSubstitution(iteratedValueType, collectionClass)) && isCollectCall(tb)) {
|
||||
boolean addAll = !tb.hasOperations() && isAddAllCall(tb);
|
||||
if (isCollectCall(tb)) {
|
||||
boolean addAll = statement instanceof PsiForeachStatement && !tb.hasOperations() && isAddAllCall(tb);
|
||||
String methodName;
|
||||
if(addAll) {
|
||||
methodName = "addAll";
|
||||
@@ -535,7 +557,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
}
|
||||
// do not replace for(T e : arr) {} with Arrays.stream(arr).forEach(e -> {}) even if flag is set
|
||||
else if (SUGGEST_FOREACH &&
|
||||
(tb.hasOperations() || (!isArray && (REPLACE_TRIVIAL_FOREACH || !isTrivial(body, statement.getIterationParameter()))))) {
|
||||
(tb.hasOperations() || (!(source instanceof ArrayStream) && (REPLACE_TRIVIAL_FOREACH || !isTrivial(body, statement))))) {
|
||||
ReplaceWithForeachCallFix forEachFix = new ReplaceWithForeachCallFix("forEach");
|
||||
LocalQuickFix[] fixes = {forEachFix};
|
||||
if (tb.hasOperations()) { //for .stream()
|
||||
@@ -548,8 +570,8 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
if (nonFinalVariables.isEmpty() && tb.getSingleStatement() instanceof PsiReturnStatement) {
|
||||
handleSingleReturn(statement, tb);
|
||||
}
|
||||
// Intermediate ops should not refer to non-final variables
|
||||
if (tb.intermediateExpressions()
|
||||
// Source and intermediate ops should not refer to non-final variables
|
||||
if (tb.intermediateAndSourceExpressions()
|
||||
.flatCollection(expr -> PsiTreeUtil.collectElementsOfType(expr, PsiReferenceExpression.class))
|
||||
.map(PsiReferenceExpression::resolve).anyMatch(nonFinalVariables::contains)) {
|
||||
return;
|
||||
@@ -561,7 +583,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
return;
|
||||
}
|
||||
if (ReferencesSearch.search(tb.getVariable(), new LocalSearchScope(statements)).findFirst() == null
|
||||
&& exitPoints.size() == 1 && exitPoints.contains(breakStatement)) {
|
||||
&& exitPoints.size() == 1 && exitPoints.contains(breakStatement)) {
|
||||
registerProblem(statement, "anyMatch", new ReplaceWithMatchFix("anyMatch"));
|
||||
return;
|
||||
}
|
||||
@@ -583,14 +605,14 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
}
|
||||
}
|
||||
|
||||
boolean canCollect(PsiForeachStatement statement, PsiMethodCallExpression methodCallExpression) {
|
||||
boolean canCollect(PsiLoopStatement statement, PsiMethodCallExpression methodCallExpression) {
|
||||
if(methodCallExpression == null) return false;
|
||||
PsiLocalVariable variable = extractCollectionVariable(methodCallExpression.getMethodExpression().getQualifierExpression());
|
||||
if(variable == null) return false;
|
||||
return getInitializerUsageStatus(variable, statement) != UNKNOWN;
|
||||
}
|
||||
|
||||
void handleSingleReturn(PsiForeachStatement statement, TerminalBlock tb) {
|
||||
void handleSingleReturn(PsiLoopStatement statement, TerminalBlock tb) {
|
||||
PsiReturnStatement returnStatement = (PsiReturnStatement)tb.getSingleStatement();
|
||||
PsiExpression value = returnStatement.getReturnValue();
|
||||
PsiReturnStatement nextReturnStatement = getNextReturnStatement(statement);
|
||||
@@ -616,7 +638,10 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
}
|
||||
if (!isVariableReferenced(tb.getVariable(), value)) {
|
||||
Operation lastOp = tb.getLastOperation();
|
||||
if(!REPLACE_TRIVIAL_FOREACH && lastOp == null || (lastOp instanceof FilterOp && lastOp.getPreviousOp() == null)) return;
|
||||
if (!REPLACE_TRIVIAL_FOREACH && lastOp instanceof StreamSource ||
|
||||
(lastOp instanceof FilterOp && lastOp.getPreviousOp() instanceof StreamSource)) {
|
||||
return;
|
||||
}
|
||||
registerProblem(statement, "anyMatch", new ReplaceWithMatchFix("anyMatch"));
|
||||
}
|
||||
if(nextReturnStatement != null && ExpressionUtils.isSimpleExpression(nextReturnStatement.getReturnValue())
|
||||
@@ -625,13 +650,8 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isRawSubstitution(PsiType iteratedValueType, PsiClass collectionClass) {
|
||||
return iteratedValueType instanceof PsiClassType && PsiUtil
|
||||
.isRawSubstitutor(collectionClass, TypeConversionUtil.getSuperClassSubstitutor(collectionClass, (PsiClassType)iteratedValueType));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private TextRange getRange(PsiForeachStatement statement) {
|
||||
private TextRange getRange(PsiLoopStatement statement) {
|
||||
boolean wholeStatement = false;
|
||||
if(myIsOnTheFly) {
|
||||
if (myKey == null) {
|
||||
@@ -643,18 +663,28 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
wholeStatement = HighlightDisplayLevel.DO_NOT_SHOW.equals(level);
|
||||
}
|
||||
}
|
||||
PsiExpression iteratedValue = statement.getIteratedValue();
|
||||
LOG.assertTrue(iteratedValue != null);
|
||||
PsiJavaToken rParenth = statement.getRParenth();
|
||||
if(wholeStatement && rParenth != null) {
|
||||
return new TextRange(statement.getTextOffset(), rParenth.getTextOffset() + 1);
|
||||
if(statement instanceof PsiForeachStatement) {
|
||||
PsiJavaToken rParenth = ((PsiForeachStatement)statement).getRParenth();
|
||||
if (wholeStatement && rParenth != null) {
|
||||
return new TextRange(statement.getTextOffset(), rParenth.getTextOffset() + 1);
|
||||
}
|
||||
PsiExpression iteratedValue = ((PsiForeachStatement)statement).getIteratedValue();
|
||||
LOG.assertTrue(iteratedValue != null);
|
||||
return iteratedValue.getTextRange();
|
||||
} else if(statement instanceof PsiForStatement) {
|
||||
PsiJavaToken rParenth = ((PsiForStatement)statement).getRParenth();
|
||||
if (wholeStatement && rParenth != null) {
|
||||
return new TextRange(statement.getTextOffset(), rParenth.getTextOffset() + 1);
|
||||
}
|
||||
PsiStatement initialization = ((PsiForStatement)statement).getInitialization();
|
||||
LOG.assertTrue(initialization != null);
|
||||
return initialization.getTextRange();
|
||||
} else {
|
||||
throw new IllegalStateException("Unexpected statement type: "+statement);
|
||||
}
|
||||
return iteratedValue.getTextRange();
|
||||
}
|
||||
|
||||
private void registerProblem(PsiForeachStatement statement, String methodName, LocalQuickFix... fixes) {
|
||||
PsiExpression iteratedValue = statement.getIteratedValue();
|
||||
LOG.assertTrue(iteratedValue != null);
|
||||
private void registerProblem(PsiLoopStatement statement, String methodName, LocalQuickFix... fixes) {
|
||||
myHolder.registerProblem(statement, getRange(statement).shiftRight(-statement.getTextOffset()),
|
||||
"Can be replaced with '" + methodName + "' call", fixes);
|
||||
}
|
||||
@@ -700,7 +730,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static PsiMethodCallExpression extractToArrayExpression(PsiForeachStatement statement, PsiMethodCallExpression expression) {
|
||||
static PsiMethodCallExpression extractToArrayExpression(PsiLoopStatement statement, PsiMethodCallExpression expression) {
|
||||
// return collection.toArray() or collection.toArray(new Type[0]) or collection.toArray(new Type[collection.size()]);
|
||||
PsiElement nextElement = PsiTreeUtil.skipSiblingsForward(statement, PsiComment.class, PsiWhiteSpace.class);
|
||||
PsiExpression toArrayCandidate;
|
||||
@@ -799,7 +829,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
return StreamEx.of(myExpression);
|
||||
}
|
||||
|
||||
abstract String createReplacement(PsiElementFactory factory);
|
||||
abstract String createReplacement();
|
||||
}
|
||||
|
||||
static class FilterOp extends Operation {
|
||||
@@ -815,7 +845,8 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createReplacement(PsiElementFactory factory) {
|
||||
public String createReplacement() {
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(myExpression.getProject());
|
||||
PsiExpression intermediate = makeIntermediateExpression(factory);
|
||||
PsiExpression expression =
|
||||
myNegated ? factory.createExpressionFromText(BoolUtils.getNegatedExpressionText(intermediate), myExpression) : intermediate;
|
||||
@@ -858,7 +889,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createReplacement(PsiElementFactory factory) {
|
||||
public String createReplacement() {
|
||||
if (isIdentityMapping(myVariable, myExpression)) {
|
||||
if (!(myType instanceof PsiPrimitiveType)) {
|
||||
return myVariable.getType() instanceof PsiPrimitiveType ? ".boxed()" : "";
|
||||
@@ -894,20 +925,33 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
|
||||
static class FlatMapOp extends Operation {
|
||||
private final PsiLoopStatement myLoop;
|
||||
private final StreamSource mySource;
|
||||
|
||||
FlatMapOp(@Nullable Operation previousOp, PsiExpression expression, PsiVariable variable, PsiLoopStatement loop) {
|
||||
super(previousOp, expression, variable);
|
||||
FlatMapOp(@Nullable Operation previousOp, StreamSource source, PsiVariable variable, PsiLoopStatement loop) {
|
||||
super(previousOp, source.getExpression(), variable);
|
||||
myLoop = loop;
|
||||
mySource = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createReplacement(PsiElementFactory factory) {
|
||||
return ".flatMap(" + myVariable.getName() + " -> " + getStreamExpression() + ")";
|
||||
public String createReplacement() {
|
||||
String operation = "flatMap";
|
||||
PsiType type = mySource.getVariable().getType();
|
||||
if(type instanceof PsiPrimitiveType && !type.equals(myVariable.getType())) {
|
||||
if(type.equals(PsiType.INT)) {
|
||||
operation = "flatMapToInt";
|
||||
} else if(type.equals(PsiType.LONG)) {
|
||||
operation = "flatMapToLong";
|
||||
} else if(type.equals(PsiType.DOUBLE)) {
|
||||
operation = "flatMapToDouble";
|
||||
}
|
||||
}
|
||||
return "." + operation + "(" + myVariable.getName() + " -> " + getStreamExpression() + ")";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
String getStreamExpression() {
|
||||
return myExpression.getText() + ".stream()";
|
||||
return mySource.createReplacement();
|
||||
}
|
||||
|
||||
boolean breaksMe(PsiBreakStatement statement) {
|
||||
@@ -915,35 +959,155 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
}
|
||||
}
|
||||
|
||||
static class ArrayFlatMapOp extends FlatMapOp {
|
||||
ArrayFlatMapOp(@Nullable Operation previousOp, PsiExpression expression, PsiVariable variable, PsiLoopStatement loop) {
|
||||
super(previousOp, expression, variable, loop);
|
||||
abstract static class StreamSource extends Operation {
|
||||
protected StreamSource(PsiVariable variable, PsiExpression expression) {
|
||||
super(null, expression, variable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createReplacement(PsiElementFactory factory) {
|
||||
String operation = "flatMap";
|
||||
PsiType type = myExpression.getType();
|
||||
if(type instanceof PsiArrayType) {
|
||||
PsiType componentType = ((PsiArrayType)type).getComponentType();
|
||||
if(componentType instanceof PsiPrimitiveType) {
|
||||
if(componentType.equals(PsiType.INT)) {
|
||||
operation = "flatMapToInt";
|
||||
} else if(componentType.equals(PsiType.LONG)) {
|
||||
operation = "flatMapToLong";
|
||||
} else if(componentType.equals(PsiType.DOUBLE)) {
|
||||
operation = "flatMapToDouble";
|
||||
}
|
||||
}
|
||||
@Contract("null -> null")
|
||||
static StreamSource tryCreate(PsiLoopStatement statement) {
|
||||
if(statement instanceof PsiForStatement) {
|
||||
return CountingLoop.from((PsiForStatement)statement);
|
||||
}
|
||||
return "." + operation + "(" + myVariable.getName() + " -> " + getStreamExpression() + ")";
|
||||
if(statement instanceof PsiForeachStatement) {
|
||||
ArrayStream source = ArrayStream.from((PsiForeachStatement)statement);
|
||||
return source == null ? CollectionStream.from((PsiForeachStatement)statement) : source;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static class ArrayStream extends StreamSource {
|
||||
private ArrayStream(PsiVariable variable, PsiExpression expression) {
|
||||
super(variable, expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
String getStreamExpression() {
|
||||
String createReplacement() {
|
||||
return "java.util.Arrays.stream("+myExpression.getText() + ")";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ArrayStream from(PsiForeachStatement statement) {
|
||||
PsiExpression iteratedValue = statement.getIteratedValue();
|
||||
if (iteratedValue == null) return null;
|
||||
|
||||
PsiType iteratedValueType = iteratedValue.getType();
|
||||
PsiParameter parameter = statement.getIterationParameter();
|
||||
|
||||
if (!(iteratedValueType instanceof PsiArrayType) ||
|
||||
!isSupported(((PsiArrayType)iteratedValueType).getComponentType()) ||
|
||||
((parameter.getType() instanceof PsiPrimitiveType) &&
|
||||
!parameter.getType().equals(((PsiArrayType)iteratedValueType).getComponentType()))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ArrayStream(parameter, iteratedValue);
|
||||
}
|
||||
}
|
||||
|
||||
static class CollectionStream extends StreamSource {
|
||||
|
||||
private CollectionStream(PsiVariable variable, PsiExpression expression) {
|
||||
super(variable, expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
String createReplacement() {
|
||||
return ParenthesesUtils.getText(myExpression, ParenthesesUtils.POSTFIX_PRECEDENCE) + ".stream()";
|
||||
}
|
||||
|
||||
@Contract("null, _ -> false")
|
||||
static boolean isRawSubstitution(PsiType iteratedValueType, PsiClass collectionClass) {
|
||||
return iteratedValueType instanceof PsiClassType && PsiUtil
|
||||
.isRawSubstitutor(collectionClass, TypeConversionUtil.getSuperClassSubstitutor(collectionClass, (PsiClassType)iteratedValueType));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static CollectionStream from(PsiForeachStatement statement) {
|
||||
PsiExpression iteratedValue = statement.getIteratedValue();
|
||||
if (iteratedValue == null) return null;
|
||||
|
||||
PsiType iteratedValueType = iteratedValue.getType();
|
||||
PsiClass collectionClass =
|
||||
JavaPsiFacade.getInstance(statement.getProject()).findClass(CommonClassNames.JAVA_UTIL_COLLECTION, statement.getResolveScope());
|
||||
PsiClass iteratorClass = PsiUtil.resolveClassInClassTypeOnly(iteratedValueType);
|
||||
if (collectionClass == null ||
|
||||
!InheritanceUtil.isInheritorOrSelf(iteratorClass, collectionClass, true) ||
|
||||
isRawSubstitution(iteratedValueType, collectionClass)) {
|
||||
return null;
|
||||
}
|
||||
return new CollectionStream(statement.getIterationParameter(), iteratedValue);
|
||||
}
|
||||
}
|
||||
|
||||
static class CountingLoop extends StreamSource {
|
||||
final PsiExpression myBound;
|
||||
final boolean myIncluding;
|
||||
|
||||
private CountingLoop(PsiLocalVariable counter, PsiExpression initializer, PsiExpression bound, boolean including) {
|
||||
super(counter, initializer);
|
||||
myBound = bound;
|
||||
myIncluding = including;
|
||||
}
|
||||
|
||||
@Override
|
||||
StreamEx<PsiExpression> expressions() {
|
||||
return StreamEx.of(myExpression, myBound);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createReplacement() {
|
||||
String className = myVariable.getType().equals(PsiType.LONG) ? "java.util.stream.LongStream" : "java.util.stream.IntStream";
|
||||
String methodName = myIncluding ? "rangeClosed" : "range";
|
||||
return className+"."+methodName+"("+myExpression.getText()+", "+myBound.getText()+")";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static CountingLoop from(PsiForStatement forStatement) {
|
||||
// check that initialization is for(int/long i = <initial_value>;...;...)
|
||||
if(!(forStatement.getInitialization() instanceof PsiDeclarationStatement)) return null;
|
||||
PsiDeclarationStatement initialization = (PsiDeclarationStatement)forStatement.getInitialization();
|
||||
if(initialization.getDeclaredElements().length != 1) return null;
|
||||
PsiElement declaration = initialization.getDeclaredElements()[0];
|
||||
if(!(declaration instanceof PsiLocalVariable)) return null;
|
||||
PsiLocalVariable counter = (PsiLocalVariable)declaration;
|
||||
if(!counter.getType().equals(PsiType.INT) && !counter.getType().equals(PsiType.LONG)) return null;
|
||||
|
||||
PsiExpression initializer = counter.getInitializer();
|
||||
if(initializer == null) return null;
|
||||
|
||||
// check that increment is like for(...;...;i++)
|
||||
if(!(forStatement.getUpdate() instanceof PsiExpressionStatement)) return null;
|
||||
PsiExpression lValue = extractIncrementedLValue(((PsiExpressionStatement)forStatement.getUpdate()).getExpression());
|
||||
if(!(lValue instanceof PsiReferenceExpression) || ((PsiReferenceExpression)lValue).resolve() != counter) return null;
|
||||
|
||||
// check that condition is like for(...;i<bound;...) or for(...;i<=bound;...)
|
||||
if(!(forStatement.getCondition() instanceof PsiBinaryExpression)) return null;
|
||||
PsiBinaryExpression condition = (PsiBinaryExpression)forStatement.getCondition();
|
||||
IElementType type = condition.getOperationTokenType();
|
||||
boolean closed = false;
|
||||
PsiExpression bound;
|
||||
PsiExpression ref;
|
||||
if(type.equals(JavaTokenType.LE)) {
|
||||
bound = condition.getROperand();
|
||||
ref = condition.getLOperand();
|
||||
closed = true;
|
||||
} else if(type.equals(JavaTokenType.LT)) {
|
||||
bound = condition.getROperand();
|
||||
ref = condition.getLOperand();
|
||||
} else if(type.equals(JavaTokenType.GE)) {
|
||||
bound = condition.getLOperand();
|
||||
ref = condition.getROperand();
|
||||
closed = true;
|
||||
} else if(type.equals(JavaTokenType.GT)) {
|
||||
bound = condition.getLOperand();
|
||||
ref = condition.getROperand();
|
||||
} else return null;
|
||||
if(bound == null || !(ref instanceof PsiReferenceExpression) || ((PsiReferenceExpression)ref).resolve() != counter) return null;
|
||||
if(!TypeConversionUtil.areTypesAssignmentCompatible(counter.getType(), bound)) return null;
|
||||
return new CountingLoop(counter, initializer, bound, closed);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -952,11 +1116,12 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
* some intermediate operations extracted.
|
||||
*/
|
||||
static class TerminalBlock {
|
||||
private final @Nullable Operation myPreviousOp;
|
||||
private final @NotNull Operation myPreviousOp;
|
||||
private final @NotNull PsiVariable myVariable;
|
||||
private final @NotNull PsiStatement[] myStatements;
|
||||
|
||||
private TerminalBlock(@Nullable Operation previousOp, @NotNull PsiVariable variable, @NotNull PsiStatement... statements) {
|
||||
// At least one previous operation is present (stream source)
|
||||
private TerminalBlock(@NotNull Operation previousOp, @NotNull PsiVariable variable, @NotNull PsiStatement... statements) {
|
||||
myVariable = variable;
|
||||
while(true) {
|
||||
if(statements.length == 1 && statements[0] instanceof PsiBlockStatement) {
|
||||
@@ -1052,46 +1217,32 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
TerminalBlock withFilter = extractFilter();
|
||||
if(withFilter != null) return withFilter;
|
||||
// extract flatMap
|
||||
if(getSingleStatement() instanceof PsiForeachStatement) {
|
||||
// flatMapping of primitive variable is not supported yet
|
||||
if(myVariable.getType() instanceof PsiPrimitiveType) return null;
|
||||
PsiForeachStatement foreachStatement = (PsiForeachStatement)getSingleStatement();
|
||||
final PsiExpression iteratedValue = foreachStatement.getIteratedValue();
|
||||
final PsiStatement body = foreachStatement.getBody();
|
||||
if (iteratedValue != null && body != null) {
|
||||
final PsiType iteratedValueType = iteratedValue.getType();
|
||||
FlatMapOp op = null;
|
||||
if(iteratedValueType instanceof PsiArrayType) {
|
||||
if (!isSupported(((PsiArrayType)iteratedValueType).getComponentType())) return null;
|
||||
op = new ArrayFlatMapOp(myPreviousOp, iteratedValue, myVariable, foreachStatement);
|
||||
} else {
|
||||
final PsiClass iteratorClass = PsiUtil.resolveClassInClassTypeOnly(iteratedValueType);
|
||||
final PsiClass collectionClass =
|
||||
JavaPsiFacade.getInstance(body.getProject())
|
||||
.findClass(CommonClassNames.JAVA_UTIL_COLLECTION, foreachStatement.getResolveScope());
|
||||
if (collectionClass != null && InheritanceUtil.isInheritorOrSelf(iteratorClass, collectionClass, true)) {
|
||||
op = new FlatMapOp(myPreviousOp, iteratedValue, myVariable, foreachStatement);
|
||||
}
|
||||
}
|
||||
if(op != null) {
|
||||
TerminalBlock withFlatMap = new TerminalBlock(op, foreachStatement.getIterationParameter(), body);
|
||||
if(ReferencesSearch.search(myVariable, new LocalSearchScope(body)).findFirst() == null) {
|
||||
return withFlatMap;
|
||||
} else {
|
||||
// Try extract nested filter like this:
|
||||
// for(List subList : list) for(T t : subList) if(condition.test(t)) { ...; break; }
|
||||
// if t is not used in "...", then this could be converted to
|
||||
// list.stream().filter(subList -> subList.stream().anyMatch(condition)).forEach(subList -> ...)
|
||||
TerminalBlock withFlatMapFilter = withFlatMap.extractFilter();
|
||||
if(withFlatMapFilter != null && !withFlatMapFilter.isEmpty()) {
|
||||
PsiStatement[] statements = withFlatMapFilter.getStatements();
|
||||
PsiStatement lastStatement = statements[statements.length-1];
|
||||
if (lastStatement instanceof PsiBreakStatement && op.breaksMe((PsiBreakStatement)lastStatement) &&
|
||||
ReferencesSearch.search(withFlatMapFilter.getVariable(), new LocalSearchScope(statements)).findFirst() == null) {
|
||||
return new TerminalBlock(new CompoundFilterOp((FilterOp)withFlatMapFilter.getLastOperation(), op),
|
||||
myVariable, Arrays.copyOfRange(statements, 0, statements.length-1));
|
||||
}
|
||||
}
|
||||
if(getSingleStatement() instanceof PsiLoopStatement) {
|
||||
PsiLoopStatement loopStatement = (PsiLoopStatement)getSingleStatement();
|
||||
StreamSource source = StreamSource.tryCreate(loopStatement);
|
||||
final PsiStatement body = loopStatement.getBody();
|
||||
if(source == null || body == null) return null;
|
||||
// flatMap from primitive to primitive is supported only if primitive types match
|
||||
// otherwise it would be necessary to create bogus step like
|
||||
// .mapToObj(var -> blahblah.stream()).flatMap(Function.identity())
|
||||
if(myVariable.getType() instanceof PsiPrimitiveType && !myVariable.getType().equals(source.getVariable().getType())) return null;
|
||||
FlatMapOp op = new FlatMapOp(myPreviousOp, source, myVariable, loopStatement);
|
||||
TerminalBlock withFlatMap = new TerminalBlock(op, source.getVariable(), body);
|
||||
if(ReferencesSearch.search(myVariable, new LocalSearchScope(body)).findFirst() == null) {
|
||||
return withFlatMap;
|
||||
} else {
|
||||
// Try extract nested filter like this:
|
||||
// for(List subList : list) for(T t : subList) if(condition.test(t)) { ...; break; }
|
||||
// if t is not used in "...", then this could be converted to
|
||||
// list.stream().filter(subList -> subList.stream().anyMatch(condition)).forEach(subList -> ...)
|
||||
TerminalBlock withFlatMapFilter = withFlatMap.extractFilter();
|
||||
if(withFlatMapFilter != null && !withFlatMapFilter.isEmpty()) {
|
||||
PsiStatement[] statements = withFlatMapFilter.getStatements();
|
||||
PsiStatement lastStatement = statements[statements.length-1];
|
||||
if (lastStatement instanceof PsiBreakStatement && op.breaksMe((PsiBreakStatement)lastStatement) &&
|
||||
ReferencesSearch.search(withFlatMapFilter.getVariable(), new LocalSearchScope(statements)).findFirst() == null) {
|
||||
return new TerminalBlock(new CompoundFilterOp((FilterOp)withFlatMapFilter.getLastOperation(), op),
|
||||
myVariable, Arrays.copyOfRange(statements, 0, statements.length-1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1121,7 +1272,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@NotNull
|
||||
public Operation getLastOperation() {
|
||||
return myPreviousOp;
|
||||
}
|
||||
@@ -1141,7 +1292,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
}
|
||||
|
||||
public boolean hasOperations() {
|
||||
return myPreviousOp != null;
|
||||
return !(myPreviousOp instanceof StreamSource);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
@@ -1163,6 +1314,13 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
* @return stream of physical expressions used in intermediate operations in arbitrary order
|
||||
*/
|
||||
public StreamEx<PsiExpression> intermediateExpressions() {
|
||||
return operations().remove(StreamSource.class::isInstance).flatMap(Operation::expressions);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return stream of physical expressions used in stream source and intermediate operations in arbitrary order
|
||||
*/
|
||||
public StreamEx<PsiExpression> intermediateAndSourceExpressions() {
|
||||
return operations().flatMap(Operation::expressions);
|
||||
}
|
||||
|
||||
@@ -1184,8 +1342,8 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static TerminalBlock from(PsiVariable variable, PsiStatement statement) {
|
||||
return new TerminalBlock(null, variable, statement).extractOperations();
|
||||
public static TerminalBlock from(StreamSource source, PsiStatement body) {
|
||||
return new TerminalBlock(source, source.myVariable, body).extractOperations();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,16 +107,15 @@ public class JavadocHelper {
|
||||
}
|
||||
|
||||
final CodeStyleSettings codeStyleSettings = CodeStyleSettingsManager.getInstance(psiFile.getProject()).getCurrentSettings();
|
||||
final int indentSize = codeStyleSettings.getIndentSize(psiFile.getFileType());
|
||||
int column;
|
||||
if (codeStyleSettings.JD_ALIGN_PARAM_COMMENTS) {
|
||||
column = Math.max(descriptionStartColumn, parameterNameEndColumn);
|
||||
if (column <= parameterNameEndColumn) {
|
||||
column = parameterNameEndColumn + indentSize;
|
||||
column = parameterNameEndColumn + 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
column = anchor.parameterNameEndPosition.column + indentSize;
|
||||
column = anchor.parameterNameEndPosition.column + 1;
|
||||
}
|
||||
return new LogicalPosition(anchor.parameterNameEndPosition.line, column);
|
||||
}
|
||||
|
||||
@@ -169,9 +169,9 @@ public class InferenceSession {
|
||||
return elementFactory.createType(parameter);
|
||||
}
|
||||
|
||||
public void initExpressionConstraints(PsiParameter[] parameters, PsiExpression[] args, PsiElement parent, PsiMethod method) {
|
||||
public void initExpressionConstraints(PsiParameter[] parameters, PsiExpression[] args, PsiElement parent) {
|
||||
final MethodCandidateInfo.CurrentCandidateProperties currentProperties = getCurrentProperties(parent);
|
||||
initExpressionConstraints(parameters, args, parent, method, currentProperties != null && currentProperties.isVarargs());
|
||||
initExpressionConstraints(parameters, args, parent, null, currentProperties != null && currentProperties.isVarargs());
|
||||
}
|
||||
|
||||
public void initExpressionConstraints(PsiParameter[] parameters,
|
||||
@@ -382,7 +382,6 @@ public class InferenceSession {
|
||||
final Ref<String> errorMessage = new Ref<String>();
|
||||
final PsiType targetType = getTargetTypeFromParent(parent, errorMessage, false);
|
||||
if (targetType == null && errorMessage.get() != null) {
|
||||
registerIncompatibleErrorMessage(errorMessage.get());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -393,6 +392,7 @@ public class InferenceSession {
|
||||
}
|
||||
|
||||
if (!repeatInferencePhases()) {
|
||||
resolveBounds(getInputInferenceVariablesFromTopLevelFunctionalExpressions(args, properties), initialSubstitutor);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -405,34 +405,37 @@ public class InferenceSession {
|
||||
}
|
||||
|
||||
if (!additionalConstraints.isEmpty() && !proceedWithAdditionalConstraints(additionalConstraints, ignoredConstraints)) {
|
||||
resolveBounds(getInputInferenceVariablesFromTopLevelFunctionalExpressions(args, properties), initialSubstitutor);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final PsiSubstitutor substitutor = resolveBounds(myInferenceVariables, initialSubstitutor);
|
||||
if (substitutor != null) {
|
||||
if (myContext != null) {
|
||||
myContext.putUserData(ERASED, myErased);
|
||||
}
|
||||
final Map<PsiTypeParameter, PsiType> map = substitutor.getSubstitutionMap();
|
||||
for (PsiTypeParameter parameter : map.keySet()) {
|
||||
final PsiType mapping = map.get(parameter);
|
||||
PsiTypeParameter param;
|
||||
if (parameter instanceof InferenceVariable) {
|
||||
((InferenceVariable)parameter).setInstantiation(mapping);
|
||||
if (((InferenceVariable)parameter).getCallContext() != myContext) {
|
||||
//don't include in result substitutor foreign inference variables
|
||||
continue;
|
||||
resolveBounds(myInferenceVariables, initialSubstitutor);
|
||||
}
|
||||
|
||||
private Collection<InferenceVariable> getInputInferenceVariablesFromTopLevelFunctionalExpressions(PsiExpression[] args, MethodCandidateInfo.CurrentCandidateProperties properties) {
|
||||
if (args == null) return Collections.emptyList();
|
||||
final PsiMethod method = properties.getMethod();
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
final HashSet<InferenceVariable> dependencies = new HashSet<InferenceVariable>();
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
PsiExpression arg = args[i];
|
||||
if (arg instanceof PsiLambdaExpression && !((PsiLambdaExpression)arg).hasFormalParameterTypes() ||
|
||||
arg instanceof PsiMethodReferenceExpression && !((PsiMethodReferenceExpression)arg).isExact()) {
|
||||
final PsiSubstitutor nestedSubstitutor = myInferenceSessionContainer.findNestedSubstitutor(arg, myInferenceSubstitution);
|
||||
final PsiType parameterType = nestedSubstitutor.substitute(getParameterType(parameters, i, mySiteSubstitutor, properties.isVarargs()));
|
||||
final PsiClassType.ClassResolveResult result = PsiUtil.resolveGenericsClassInType(parameterType);
|
||||
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(result);
|
||||
if (interfaceMethod != null) {
|
||||
final PsiSubstitutor substitutor = LambdaUtil.getSubstitutor(interfaceMethod, result);
|
||||
for (PsiParameter parameter : interfaceMethod.getParameterList().getParameters()) {
|
||||
collectDependencies(substitutor.substitute(parameter.getType()), dependencies);
|
||||
}
|
||||
param = ((InferenceVariable)parameter).getParameter();
|
||||
}
|
||||
else {
|
||||
param = parameter;
|
||||
}
|
||||
mySiteSubstitutor = mySiteSubstitutor.put(param, mapping);
|
||||
}
|
||||
}
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
private boolean isOverloadCheck() {
|
||||
@@ -1106,8 +1109,8 @@ public class InferenceSession {
|
||||
return false;
|
||||
}
|
||||
|
||||
private PsiSubstitutor resolveBounds(final Collection<InferenceVariable> inferenceVariables,
|
||||
PsiSubstitutor substitutor) {
|
||||
private void resolveBounds(final Collection<InferenceVariable> inferenceVariables,
|
||||
@NotNull PsiSubstitutor substitutor) {
|
||||
final Collection<InferenceVariable> allVars = new ArrayList<InferenceVariable>(inferenceVariables);
|
||||
while (!allVars.isEmpty()) {
|
||||
final List<InferenceVariable> vars = InferenceVariablesOrder.resolveOrder(allVars, this);
|
||||
@@ -1132,15 +1135,36 @@ public class InferenceSession {
|
||||
}
|
||||
|
||||
if (!initFreshVariables(substitutor, unresolved)) {
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
|
||||
myIncorporationPhase.forgetCaptures(vars);
|
||||
if (!repeatInferencePhases()) {
|
||||
return null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return substitutor;
|
||||
|
||||
if (myContext != null) {
|
||||
myContext.putUserData(ERASED, myErased);
|
||||
}
|
||||
|
||||
final Map<PsiTypeParameter, PsiType> map = substitutor.getSubstitutionMap();
|
||||
for (PsiTypeParameter parameter : map.keySet()) {
|
||||
final PsiType mapping = map.get(parameter);
|
||||
PsiTypeParameter param;
|
||||
if (parameter instanceof InferenceVariable) {
|
||||
((InferenceVariable)parameter).setInstantiation(mapping);
|
||||
if (((InferenceVariable)parameter).getCallContext() != myContext) {
|
||||
//don't include in result substitutor foreign inference variables
|
||||
continue;
|
||||
}
|
||||
param = ((InferenceVariable)parameter).getParameter();
|
||||
}
|
||||
else {
|
||||
param = parameter;
|
||||
}
|
||||
mySiteSubstitutor = mySiteSubstitutor.put(param, mapping);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean initFreshVariables(PsiSubstitutor substitutor, List<InferenceVariable> vars) {
|
||||
|
||||
@@ -138,7 +138,7 @@ public class InferenceSessionContainer {
|
||||
}
|
||||
|
||||
final InferenceSession inferenceSession = new InferenceSession(typeParameters, partialSubstitutor, parent.getManager(), parent, policy);
|
||||
inferenceSession.initExpressionConstraints(parameters, arguments, parent, null);
|
||||
inferenceSession.initExpressionConstraints(parameters, arguments, parent);
|
||||
return inferenceSession.infer(parameters, arguments, parent);
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ public class PsiGraphInferenceHelper implements PsiInferenceHelper {
|
||||
}
|
||||
else {
|
||||
final InferenceSession inferenceSession = new InferenceSession(new PsiTypeParameter[]{typeParameter}, partialSubstitutor, myManager, null);
|
||||
inferenceSession.initExpressionConstraints(parameters, arguments, null, null);
|
||||
inferenceSession.initExpressionConstraints(parameters, arguments, null);
|
||||
substitutor = inferenceSession.infer();
|
||||
}
|
||||
return substitutor.substitute(typeParameter);
|
||||
|
||||
@@ -3,8 +3,8 @@ import java.util.*;
|
||||
class Main {
|
||||
|
||||
void foo(List<Integer> list) {
|
||||
bar(list, i -> <error descr="Bad return type in lambda expression: int cannot be converted to S_OUT">i.intValue()</error>, i -> i.<error descr="Cannot resolve method 'unknown()'">unknown</error>());
|
||||
bar1(list, i -> <error descr="Bad return type in lambda expression: int cannot be converted to S_OUT">i.intValue()</error>, i -> i.<error descr="Cannot resolve method 'unknown()'">unknown</error>());
|
||||
bar(list, i -> i.intValue(), i -> i.<error descr="Cannot resolve method 'unknown()'">unknown</error>());
|
||||
bar1(list, i -> i.intValue(), i -> i.<error descr="Cannot resolve method 'unknown()'">unknown</error>());
|
||||
}
|
||||
|
||||
<U, S_IN, S_OUT, R> R bar(List<S_IN> list,
|
||||
|
||||
@@ -57,7 +57,7 @@ class ReturnTypeCompatibility {
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
<error descr="Ambiguous method call: both 'ReturnTypeCompatibility.call(I1<Number>)' and 'ReturnTypeCompatibility.call(I2<P>)' match">call</error>(i-> {return i;});
|
||||
<error descr="Ambiguous method call: both 'ReturnTypeCompatibility.call(I1<Number>)' and 'ReturnTypeCompatibility.call(I2<String>)' match">call</error>(i-> {return i;});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
class A {
|
||||
{
|
||||
run(A.class, this, (o) -> {
|
||||
o.meth();
|
||||
<error descr="Missing return statement">}</error>);
|
||||
|
||||
|
||||
Map<Integer, Integer> map = Stream.iterate(5, <error descr="no instance(s) of type variable(s) T exist so that Stream<T> conforms to Map<Integer, Integer>">t -> t + 5</error>);
|
||||
}
|
||||
|
||||
|
||||
void meth() {}
|
||||
|
||||
<T> T run(Class<T> c, T t, Function<T, T> f) {
|
||||
return f.apply(t);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Replace with anyMatch()" "true"
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public void testAssignment(List<String> data) {
|
||||
String[] found = {"no"};
|
||||
if (data.stream().map(String::trim).anyMatch(trimmed -> !trimmed.isEmpty())) {
|
||||
found[0] = "yes";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// "Replace with anyMatch()" "true"
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
boolean find(List<String> data) {
|
||||
if(data != null) {
|
||||
return data.stream().map(String::trim).anyMatch(trimmed -> trimmed.startsWith("xyz"));
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// "Replace with findFirst()" "true"
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public class Main {
|
||||
private int getInitialSize() {return 0;}
|
||||
|
||||
public void testMap(Map<String, List<String>> map) throws Exception {
|
||||
int firstSize = 10;
|
||||
|
||||
System.out.println(firstSize);
|
||||
|
||||
// loop
|
||||
// comment
|
||||
firstSize = map.values().stream().filter(Objects::nonNull).findFirst().map(List::size).orElse(getInitialSize());
|
||||
System.out.println(firstSize);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// "Replace with findFirst()" "true"
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public static String find(List<List<String>> list) {
|
||||
if(list == null) {
|
||||
System.out.println("oops");
|
||||
return "";
|
||||
} else {
|
||||
return list.stream().flatMap(Collection::stream).filter(string -> string.startsWith("ABC")).findFirst().orElse(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// "Replace with findFirst()" "true"
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class Main {
|
||||
public String testNestedForLoop(int[] data, List<String> info) {
|
||||
return Arrays.stream(data).flatMap(val -> IntStream.rangeClosed(0, val)).mapToObj(info::get).filter(str -> !str.isEmpty()).findFirst().orElse(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Replace with collect" "true"
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class Main {
|
||||
public void testForLoop(List<String> input) {
|
||||
List<Integer> result = IntStream.range(0, 10).mapToObj(i -> input.get(i).length()).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Replace with collect" "true"
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class Main {
|
||||
public void testForLoop() {
|
||||
List<Integer> result = IntStream.rangeClosed(0, 10).boxed().collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// "Replace with collect" "true"
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class Main {
|
||||
public void testForLoop(List<String> input) {
|
||||
List<Integer> result;
|
||||
short s = (short)input.size();
|
||||
result = IntStream.range(0, s).mapToObj(i -> input.get(i).length()).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import java.util.Arrays;
|
||||
|
||||
// "Replace with forEach" "true"
|
||||
public class Main {
|
||||
public void test(int[] arr) {
|
||||
Arrays.stream(arr).filter(i -> i > 0).forEach(System.out::println);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// "Replace with anyMatch()" "true"
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public void testAssignment(List<String> data) {
|
||||
String[] found = {"no"};
|
||||
for(String str : da<caret>ta) {
|
||||
String trimmed = str.trim();
|
||||
if(!trimmed.isEmpty()) {
|
||||
found[0] = "yes";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// "Replace with anyMatch()" "true"
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
boolean find(List<String> data) {
|
||||
if(data != null) {
|
||||
for (String e : da<caret>ta) {
|
||||
String trimmed = e.trim();
|
||||
if (trimmed.startsWith("xyz")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// "Replace with findFirst()" "true"
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Main {
|
||||
private int getInitialSize() {return 0;}
|
||||
|
||||
public void testMap(Map<String, List<String>> map) throws Exception {
|
||||
int firstSize = 10;
|
||||
|
||||
System.out.println(firstSize);
|
||||
|
||||
firstSize = getInitialSize();
|
||||
// loop
|
||||
for(List<String> list : map.valu<caret>es()) {
|
||||
if(list != null) {
|
||||
firstSize = list.size();
|
||||
// comment
|
||||
break;
|
||||
}
|
||||
}
|
||||
System.out.println(firstSize);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// "Replace with findFirst()" "true"
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public static String find(List<List<String>> list) {
|
||||
if(list == null) {
|
||||
System.out.println("oops");
|
||||
return "";
|
||||
} else {
|
||||
for (List<String> innerList : lis<caret>t) {
|
||||
for (String string : innerList) {
|
||||
if (string.startsWith("ABC")) {
|
||||
return string;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// "Replace with findFirst()" "false"
|
||||
|
||||
public class Main {
|
||||
public boolean check(int value) {
|
||||
return value == 3;
|
||||
}
|
||||
|
||||
public void find() {
|
||||
int end = 10;
|
||||
for(<caret>int i=0; i<end; i++) {
|
||||
if(check(i)) {
|
||||
end = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
System.out.println(end);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// "Replace with findFirst()" "true"
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public String testNestedForLoop(int[] data, List<String> info) {
|
||||
for(int val : da<caret>ta) {
|
||||
for(int x = 0; x <= val; x++) {
|
||||
String str = info.get(x);
|
||||
if(!str.isEmpty()) {
|
||||
return str;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// "Replace with collect" "true"
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public void testForLoop(List<String> input) {
|
||||
List<Integer> result = new ArrayList<>();
|
||||
for (in<caret>t i = 0; i < 10; i++) {
|
||||
result.add(input.get(i).length());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// "Replace with collect" "true"
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public void testForLoop() {
|
||||
List<Integer> result = new ArrayList<>();
|
||||
for (in<caret>t i = 0; 10 >= i; i++) {
|
||||
result.add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// "Replace with collect" "false"
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public void testForLoop(List<String> input) {
|
||||
List<Integer> result = new ArrayList<>();
|
||||
float s = (float)input.size();
|
||||
for (in<caret>t i = 0; i < s; i++) {
|
||||
result.add(input.get(i).length());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// "Replace with collect" "true"
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public void testForLoop(List<String> input) {
|
||||
List<Integer> result = new ArrayList<>();
|
||||
short s = (short)input.size();
|
||||
for (in<caret>t i = 0; i < s; i++) {
|
||||
result.add(input.get(i).length());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// "Replace with collect" "false"
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public void testForLoop(List<String> input) {
|
||||
List<Integer> result = new ArrayList<>();
|
||||
for (in<caret>t i = 0; i < 10; i++) {
|
||||
result.add(input.get(i++).length());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// "Replace with collect" "false"
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public void testForLoop(List<String> input) {
|
||||
List<Integer> result = new ArrayList<>();
|
||||
for (in<caret>t i = 0; i > 10; i++) {
|
||||
result.add(input.get(i).length());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// "Replace with collect" "false"
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public void testForLoop(List<String> input) {
|
||||
List<Integer> result = new ArrayList<>();
|
||||
for (in<caret>t i = 0; i < 10; i+=2) {
|
||||
result.add(input.get(i).length());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// "Replace with collect" "false"
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public void testForLoop(List<String> input) {
|
||||
List<Integer> result = new ArrayList<>();
|
||||
for (in<caret>t i = 0, j=0; i < 10; i++) {
|
||||
result.add(input.get(i).length());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// "Replace with forEach" "false"
|
||||
// "Replace with forEach" "true"
|
||||
public class Main {
|
||||
public void test(int[] arr) {
|
||||
for(int i : arr) {
|
||||
for(int i : a<caret>rr) {
|
||||
if(i > 0) {
|
||||
System.out.println(i);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
// "Replace with forEach" "false"
|
||||
public class Main {
|
||||
public void test(int[] arr) {
|
||||
for(float i : a<caret>rr) {
|
||||
if(i > 0) {
|
||||
System.out.println(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// "Replace with sum()" "false"
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public long testFor(List<List<String>> list) {
|
||||
long count = 0;
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
for (String s : list.g<caret>et(i)) {
|
||||
String trimmed = s.trim();
|
||||
if (trimmed.isEmpty()) {
|
||||
count += i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
@@ -187,7 +187,7 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
}
|
||||
|
||||
public void testAcceptInferredVariablesBeforeAdditionalConstraintsLeadToFail() throws Exception {
|
||||
doTest(false);
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testEnsureNoCaptureIsPerformedOverTargetTypeOfCastExpressionWhichMarksFunctionalExpression() throws Exception {
|
||||
@@ -335,13 +335,13 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(false);
|
||||
public void testInferTypeParametersFromFunctionalInterfaceInputs() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest(boolean warnings) {
|
||||
private void doTest() {
|
||||
IdeaTestUtil.setTestVersion(JavaSdkVersion.JDK_1_8, getModule(), getTestRootDisposable());
|
||||
doTest(BASE_PATH + "/" + getTestName(false) + ".java", warnings, false);
|
||||
doTest(BASE_PATH + "/" + getTestName(false) + ".java", false, false);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -95,7 +95,7 @@ class Test {
|
||||
expected: '''\
|
||||
class Test {
|
||||
/**
|
||||
* @param i <caret>
|
||||
* @param i <caret>
|
||||
* @param j
|
||||
*/
|
||||
void test(int i, int j) {
|
||||
@@ -251,7 +251,7 @@ class Test {
|
||||
expected: '''\
|
||||
class Test {
|
||||
/**
|
||||
* @param i <caret>
|
||||
* @param i <caret>
|
||||
*/
|
||||
void test(int i) {
|
||||
}
|
||||
@@ -272,7 +272,7 @@ class Test {
|
||||
expected: '''\
|
||||
class Test {
|
||||
/**
|
||||
* @param i <caret>
|
||||
* @param i <caret>
|
||||
* @param j
|
||||
* @param k
|
||||
*/
|
||||
@@ -399,7 +399,7 @@ class Test<T> {<caret>
|
||||
/**
|
||||
* My description
|
||||
* @author me
|
||||
* @param <T> <caret>
|
||||
* @param <T> <caret>
|
||||
*/
|
||||
class Test<T> {
|
||||
}''')
|
||||
@@ -420,7 +420,7 @@ class Test<T, V> {
|
||||
* My description
|
||||
* @author me
|
||||
* @param <T> type description
|
||||
* @param <V> <caret>
|
||||
* @param <V> <caret>
|
||||
*/
|
||||
class Test<T, V> {
|
||||
}''')
|
||||
@@ -467,7 +467,7 @@ class Test {
|
||||
expected: '''\
|
||||
class Test {
|
||||
/**
|
||||
* @param i <caret>
|
||||
* @param i <caret>
|
||||
* @param j
|
||||
*/
|
||||
public void test(int i, int j) {
|
||||
@@ -491,7 +491,7 @@ class Test {
|
||||
class Test {
|
||||
/**
|
||||
* @param <A> A description
|
||||
* @param <B> <caret>
|
||||
* @param <B> <caret>
|
||||
*/
|
||||
<A, B> void test() {
|
||||
}
|
||||
@@ -515,7 +515,7 @@ class Test<A, B> {<caret>
|
||||
/**
|
||||
* Class description
|
||||
* @author Zigmund
|
||||
* @param <A> <caret>
|
||||
* @param <A> <caret>
|
||||
* @param <B> multi-line
|
||||
* description
|
||||
*/
|
||||
@@ -575,7 +575,7 @@ class Test {
|
||||
expected: '''\
|
||||
class Test {
|
||||
/**
|
||||
* @param i <caret>
|
||||
* @param i <caret>
|
||||
*/
|
||||
void test(int i) {
|
||||
}
|
||||
|
||||
@@ -712,16 +712,20 @@ public class DirectoryIndexTest extends IdeaTestCase {
|
||||
assertIteratedContent(myFileIndex, Arrays.asList(fileSourceRoot, fileTestSourceRoot), Collections.singletonList(fileRoot));
|
||||
}
|
||||
|
||||
private static void assertIteratedContent(ProjectFileIndex fileIndex,
|
||||
private void assertIteratedContent(Module module, @Nullable List<VirtualFile> contains, @Nullable List<VirtualFile> doesntContain) {
|
||||
assertIteratedContent(ModuleRootManager.getInstance(module).getFileIndex(), contains, doesntContain);
|
||||
assertIteratedContent(myFileIndex, contains, doesntContain);
|
||||
}
|
||||
|
||||
private static void assertIteratedContent(FileIndex fileIndex,
|
||||
@Nullable List<VirtualFile> contains,
|
||||
@Nullable List<VirtualFile> doesntContain) {
|
||||
final Set<VirtualFile> collected = new THashSet<>();
|
||||
fileIndex.iterateContent(new ContentIterator() {
|
||||
@Override
|
||||
public boolean processFile(VirtualFile fileOrDir) {
|
||||
collected.add(fileOrDir);
|
||||
return true;
|
||||
fileIndex.iterateContent(fileOrDir -> {
|
||||
if (!collected.add(fileOrDir)) {
|
||||
fail(fileOrDir + " visited twice");
|
||||
}
|
||||
return true;
|
||||
});
|
||||
if (contains != null) assertContainsElements(collected, contains);
|
||||
if (doesntContain != null) assertDoesntContain(collected, doesntContain);
|
||||
@@ -856,10 +860,61 @@ public class DirectoryIndexTest extends IdeaTestCase {
|
||||
assertTrue(myFileIndex.isInSource(fileSourceRoot));
|
||||
}
|
||||
|
||||
public void testContentRootUnderExcludedRoot() {
|
||||
VirtualFile dirUnderExcluded = createChildDirectory(myExcludeDir, "generated");
|
||||
PsiTestUtil.addSourceContentToRoots(myModule2, dirUnderExcluded);
|
||||
checkInfo(dirUnderExcluded, myModule2, false, false, "", JavaSourceRootType.SOURCE, myModule2, myModule3);
|
||||
public void testSourceContentRootsUnderExcludedRoot() {
|
||||
VirtualFile contentRoot = createChildDirectory(myExcludeDir, "content");
|
||||
PsiTestUtil.addContentRoot(myModule2, contentRoot);
|
||||
checkInfo(contentRoot, myModule2, false, false, null, null, myModule2, myModule3);
|
||||
VirtualFile excludedFile = createChildData(myExcludeDir, "excluded.txt");
|
||||
|
||||
VirtualFile sourceRoot = createChildDirectory(myExcludeDir, "src");
|
||||
VirtualFile sourceFile = createChildData(sourceRoot, "source.txt");
|
||||
PsiTestUtil.addSourceRoot(myModule2, sourceRoot);
|
||||
assertEquals(myModule2Dir, assertInProject(sourceRoot).getContentRoot());
|
||||
checkInfo(sourceRoot, myModule2, false, false, "", JavaSourceRootType.SOURCE, myModule2, myModule3);
|
||||
|
||||
VirtualFile contentSourceRoot = createChildDirectory(myExcludeDir, "content-src");
|
||||
VirtualFile contentSourceFile = createChildData(sourceRoot, "content-source.txt");
|
||||
PsiTestUtil.addSourceContentToRoots(myModule2, contentSourceRoot);
|
||||
checkInfo(contentSourceRoot, myModule2, false, false, "", JavaSourceRootType.SOURCE, myModule2, myModule3);
|
||||
|
||||
assertIteratedContent(myModule2, Arrays.asList(sourceFile, contentSourceFile, sourceRoot, contentSourceRoot),
|
||||
Arrays.asList(excludedFile, myExcludeDir));
|
||||
}
|
||||
|
||||
public void testSourceContentRootsUnderExcludedRootUnderSourceRoot() {
|
||||
VirtualFile excluded = createChildDirectory(myModule2Dir, "excluded");
|
||||
PsiTestUtil.addExcludedRoot(myModule2, excluded);
|
||||
VirtualFile excludedFile = createChildData(excluded, "excluded.txt");
|
||||
|
||||
VirtualFile contentRoot = createChildDirectory(excluded, "content");
|
||||
PsiTestUtil.addContentRoot(myModule2, contentRoot);
|
||||
checkInfo(contentRoot, myModule2, false, false, null, null);
|
||||
|
||||
VirtualFile sourceRoot = createChildDirectory(excluded, "src");
|
||||
PsiTestUtil.addSourceRoot(myModule2, sourceRoot);
|
||||
VirtualFile sourceFile = createChildData(sourceRoot, "source.txt");
|
||||
assertEquals(myModule2Dir, assertInProject(sourceRoot).getContentRoot());
|
||||
checkInfo(sourceRoot, myModule2, false, false, "", JavaSourceRootType.SOURCE, myModule2, myModule3);
|
||||
|
||||
VirtualFile contentSourceRoot = createChildDirectory(excluded, "content-src");
|
||||
VirtualFile contentSourceFile = createChildData(contentSourceRoot, "content-source.txt");
|
||||
PsiTestUtil.addSourceContentToRoots(myModule2, contentSourceRoot);
|
||||
checkInfo(contentSourceRoot, myModule2, false, false, "", JavaSourceRootType.SOURCE, myModule2, myModule3);
|
||||
|
||||
assertIteratedContent(myModule2, Arrays.asList(sourceFile, contentSourceFile, sourceRoot, contentSourceRoot),
|
||||
Arrays.asList(excludedFile, myExcludeDir));
|
||||
}
|
||||
|
||||
public void testExcludedSourceRootUnderExcluded() {
|
||||
VirtualFile excluded = createChildDirectory(myModule2Dir, "excluded");
|
||||
PsiTestUtil.addExcludedRoot(myModule2, excluded);
|
||||
|
||||
VirtualFile src = createChildDirectory(excluded, "src");
|
||||
VirtualFile sourceFile = createChildData(src, "src.txt");
|
||||
PsiTestUtil.addSourceRoot(myModule2, src);
|
||||
PsiTestUtil.addExcludedRoot(myModule2, src);
|
||||
assertExcluded(src, myModule2);
|
||||
assertIteratedContent(myModule2, null, Arrays.asList(sourceFile));
|
||||
}
|
||||
|
||||
private void checkInfo(VirtualFile file,
|
||||
|
||||
@@ -142,20 +142,44 @@ public class ProjectTreeStructureTest extends BaseProjectViewTestCase {
|
||||
ModuleManagerImpl.getInstanceImpl(myProject).setModuleGroupPath(module, new String[]{"modules"});
|
||||
PsiTestUtil.addContentRoot(module, mainModuleRoot.findFileByRelativePath("src/com/package1/p2/p3"));
|
||||
|
||||
TestProjectTreeStructure structure = new TestProjectTreeStructure(myProject, getTestRootDisposable());
|
||||
structure.setShowLibraryContents(false);
|
||||
myStructure.setShowLibraryContents(false);
|
||||
myStructure.hideExcludedFiles();
|
||||
|
||||
String structureContent = PlatformTestUtil.print(structure, structure.getRootElement(), 0, null, 10, ' ', myPrintInfo).toString();
|
||||
assertStructureEqual("Project\n" +
|
||||
" nested_module.iml\n" +
|
||||
" noDuplicateModules\n" +
|
||||
" src\n" +
|
||||
" com\n" +
|
||||
" package1\n" +
|
||||
" Test.java\n" +
|
||||
" testNoDuplicateModules.iml\n");
|
||||
}
|
||||
|
||||
Assert.assertFalse(structureContent.contains("modules"));
|
||||
assertEquals("Project\n" +
|
||||
" noDuplicateModules\n" +
|
||||
" src\n" +
|
||||
" com\n" +
|
||||
" package1\n" +
|
||||
" Test.java\n" +
|
||||
" nested_module.iml\n" +
|
||||
" testNoDuplicateModules.iml\n",
|
||||
structureContent);
|
||||
public void testContentRootUnderExcluded() {
|
||||
VirtualFile mainModuleRoot = ModuleRootManager.getInstance(myModule).getContentRoots()[0];
|
||||
|
||||
PsiTestUtil.addExcludedRoot(myModule, mainModuleRoot.findFileByRelativePath("exc"));
|
||||
|
||||
PsiTestUtil.addContentRoot(myModule, mainModuleRoot.findFileByRelativePath("exc/gen"));
|
||||
|
||||
myStructure.setShowLibraryContents(false);
|
||||
|
||||
assertStructureEqual("Project\n" +
|
||||
" contentRootUnderExcluded\n" +
|
||||
" B.txt\n" +
|
||||
" exc\n" +
|
||||
" excluded.txt\n" +
|
||||
" gen\n" +
|
||||
" A.java\n" +
|
||||
" testContentRootUnderExcluded.iml\n");
|
||||
|
||||
myStructure.hideExcludedFiles();
|
||||
assertStructureEqual("Project\n" +
|
||||
" Module\n" +
|
||||
" contentRootUnderExcluded\n" +
|
||||
" B.txt\n" +
|
||||
" gen\n" +
|
||||
" A.java\n" +
|
||||
" testContentRootUnderExcluded.iml\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,9 +65,17 @@ public abstract class BaseProjectViewTestCase extends TestSourceBasedTestCase {
|
||||
return myStructure;
|
||||
}
|
||||
|
||||
private void assertStructureEqual(PsiDirectory root, String expected, int maxRowCount, AbstractTreeStructure structure) {
|
||||
private void assertStructureEqual(PsiDirectory root, String expected, int maxRowCount, AbstractProjectTreeStructure structure) {
|
||||
assertNotNull(root);
|
||||
PsiDirectoryNode rootNode = new PsiDirectoryNode(myProject, root, (ViewSettings)structure);
|
||||
PsiDirectoryNode rootNode = new PsiDirectoryNode(myProject, root, structure);
|
||||
assertStructureEqual(expected, maxRowCount, rootNode);
|
||||
}
|
||||
|
||||
protected void assertStructureEqual(String expected) {
|
||||
assertStructureEqual(expected, -1, myStructure.getRootElement());
|
||||
}
|
||||
|
||||
private void assertStructureEqual(String expected, int maxRowCount, Object rootNode) {
|
||||
ProjectViewTestUtil.assertStructureEqual(myStructure, expected, maxRowCount, PlatformTestUtil.createComparator(myPrintInfo), rootNode, myPrintInfo);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,10 @@ import org.jetbrains.jps.model.artifact.JpsArtifact;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Allows to perform additional tasks when artifacts are built. Implementations of this class are registered as Java services, by creating
|
||||
* a file META-INF/services/org.jetbrains.jps.builders.artifacts.ArtifactBuildTaskProvider containing the qualified name of your
|
||||
* implementation class.
|
||||
*
|
||||
* @author nik
|
||||
*/
|
||||
public abstract class ArtifactBuildTaskProvider {
|
||||
@@ -38,6 +42,13 @@ public abstract class ArtifactBuildTaskProvider {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns list of tasks which need to be executed during {@code buildPhase} when {@code artifact} is building. Firstly tasks returned for
|
||||
* {@link ArtifactBuildPhase#PRE_PROCESSING PRE_PROCESSING} are executed, then files specified in the artifact layout are copied to the output directory.
|
||||
* If all files in the artifact output were up to date, i.e. no copying was performed, the build finishes. Otherwise all tasks returned for
|
||||
* {@link ArtifactBuildPhase#FINISHING_BUILD FINISHING_BUILD} are executed and then all tasks returned for
|
||||
* {@link ArtifactBuildPhase#POST_PROCESSING POST_PROCESSING} are executed.
|
||||
*/
|
||||
@NotNull
|
||||
public abstract List<? extends BuildTask> createArtifactBuildTasks(@NotNull JpsArtifact artifact, @NotNull ArtifactBuildPhase buildPhase);
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.jetbrains.jps.model.java.JpsJavaExtensionService;
|
||||
import org.jetbrains.jps.model.java.JpsJavaModuleExtension;
|
||||
import org.jetbrains.jps.model.java.JpsJavaProjectExtension;
|
||||
import org.jetbrains.jps.model.module.JpsModule;
|
||||
import org.jetbrains.jps.model.module.JpsModuleSourceRoot;
|
||||
import org.jetbrains.jps.util.JpsPathUtil;
|
||||
|
||||
import java.io.File;
|
||||
@@ -67,6 +68,11 @@ public class ModuleExcludeIndexImpl implements ModuleExcludeIndex {
|
||||
moduleContent.add(contentRoot);
|
||||
contentToModule.put(contentRoot, module);
|
||||
}
|
||||
for (JpsModuleSourceRoot root : module.getSourceRoots()) {
|
||||
File sourceRoot = root.getFile();
|
||||
moduleContent.add(sourceRoot);
|
||||
contentToModule.put(sourceRoot, module);
|
||||
}
|
||||
myModuleToExcludesMap.put(module, moduleExcludes);
|
||||
myModuleToContentMap.put(module, moduleContent);
|
||||
myExcludedRoots.addAll(moduleExcludes);
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
class B {
|
||||
A a;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/exc/src" isTestSource="false" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/exc" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/sourceRootUnderExcluded.iml" filepath="$PROJECT_DIR$/sourceRootUnderExcluded.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.6" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
class A {
|
||||
B b;
|
||||
}
|
||||
@@ -69,6 +69,17 @@ class ModuleRebuildTest: JpsRebuildTestCase() {
|
||||
})
|
||||
}
|
||||
|
||||
fun testSourceRootUnderExcluded() {
|
||||
doTest("sourceRootUnderExcluded/sourceRootUnderExcluded.ipr", fs {
|
||||
dir("production") {
|
||||
dir("sourceRootUnderExcluded") {
|
||||
file("A.class")
|
||||
file("B.class")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fun testResourceCopying() {
|
||||
doTest("resourceCopying/resourceCopying.ipr", fs {
|
||||
dir("production") {
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.intellij.openapi.util.io.FileUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.indices.impl.ModuleExcludeIndexImpl;
|
||||
import org.jetbrains.jps.model.JpsJavaModelTestCase;
|
||||
import org.jetbrains.jps.model.java.JavaSourceRootType;
|
||||
import org.jetbrains.jps.model.java.JpsJavaModuleExtension;
|
||||
import org.jetbrains.jps.model.module.JpsModule;
|
||||
import org.jetbrains.jps.util.JpsPathUtil;
|
||||
@@ -138,6 +139,24 @@ public class ModuleExcludeIndexTest extends JpsJavaModelTestCase {
|
||||
assertFalse(index.isExcludedFromModule(innerRoot, inner));
|
||||
}
|
||||
|
||||
public void testSourceRootUnderExcluded() {
|
||||
File project = new File(myRoot, "project");
|
||||
File exc = new File(project, "exc");
|
||||
File src = new File(exc, "src");
|
||||
JpsModule module = addModule();
|
||||
addContentRoot(module, project);
|
||||
addExcludedRoot(module, exc);
|
||||
addSourceRoot(module, src);
|
||||
assertNotExcluded(src);
|
||||
|
||||
addExcludedRoot(module, src);
|
||||
assertExcluded(src);
|
||||
}
|
||||
|
||||
private static void addSourceRoot(JpsModule module, File src) {
|
||||
module.addSourceRoot(JpsPathUtil.pathToUrl(src.getAbsolutePath()), JavaSourceRootType.SOURCE);
|
||||
}
|
||||
|
||||
private static void addExcludedRoot(JpsModule module, File root) {
|
||||
module.getExcludeRootsList().addUrl(JpsPathUtil.pathToUrl(root.getAbsolutePath()));
|
||||
}
|
||||
|
||||
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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 com.jetbrains.jsonSchema.impl;
|
||||
|
||||
import com.intellij.json.psi.*;
|
||||
@@ -244,7 +259,8 @@ class JsonBySchemaObjectAnnotator implements Annotator {
|
||||
}
|
||||
|
||||
private boolean checkForEnum(JsonValue value, JsonSchemaObject schema) {
|
||||
if (schema.getEnum() == null) return true;
|
||||
//enum values + pattern -> don't check enum values
|
||||
if (schema.getEnum() == null || schema.getPattern() != null) return true;
|
||||
final String text = value.getText();
|
||||
final List<Object> objects = schema.getEnum();
|
||||
for (Object object : objects) {
|
||||
|
||||
@@ -26,8 +26,10 @@ import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class RefDirectoryImpl extends RefElementImpl implements RefDirectory{
|
||||
private RefModule myRefModule;
|
||||
protected RefDirectoryImpl(PsiDirectory psiElement, RefManager refManager) {
|
||||
super(psiElement.getName(), psiElement, refManager);
|
||||
final PsiDirectory parentDirectory = psiElement.getParentDirectory();
|
||||
@@ -38,13 +40,10 @@ public class RefDirectoryImpl extends RefElementImpl implements RefDirectory{
|
||||
return;
|
||||
}
|
||||
}
|
||||
final Module module = ModuleUtilCore.findModuleForPsiElement(psiElement);
|
||||
if (module != null) {
|
||||
final RefModuleImpl refModule = (RefModuleImpl)refManager.getRefModule(module);
|
||||
if (refModule != null) {
|
||||
refModule.add(this);
|
||||
return;
|
||||
}
|
||||
myRefModule = refManager.getRefModule(ModuleUtilCore.findModuleForPsiElement(psiElement));
|
||||
if (myRefModule != null) {
|
||||
((RefModuleImpl)myRefModule).add(this);
|
||||
return;
|
||||
}
|
||||
((RefProjectImpl)refManager.getRefProject()).add(this);
|
||||
}
|
||||
@@ -54,6 +53,12 @@ public class RefDirectoryImpl extends RefElementImpl implements RefDirectory{
|
||||
ApplicationManager.getApplication().runReadAction(() -> visitor.visitDirectory(this));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public RefModule getModule() {
|
||||
return myRefModule;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initialize() {
|
||||
}
|
||||
|
||||
@@ -61,14 +61,12 @@ public abstract class RefElementImpl extends RefEntityImpl implements RefElement
|
||||
private String[] mySuppressions = null;
|
||||
|
||||
private boolean myIsDeleted ;
|
||||
private final Module myModule;
|
||||
protected static final int IS_REACHABLE_MASK = 0x40;
|
||||
|
||||
protected RefElementImpl(@NotNull String name, @NotNull RefElement owner) {
|
||||
super(name, owner.getRefManager());
|
||||
myID = null;
|
||||
myFlags = 0;
|
||||
myModule = ModuleUtilCore.findModuleForPsiElement(owner.getElement());
|
||||
}
|
||||
|
||||
protected RefElementImpl(PsiFile file, RefManager manager) {
|
||||
@@ -79,7 +77,6 @@ public abstract class RefElementImpl extends RefEntityImpl implements RefElement
|
||||
super(name, manager);
|
||||
myID = SmartPointerManager.getInstance(manager.getProject()).createSmartPsiElementPointer(element);
|
||||
myFlags = 0;
|
||||
myModule = ModuleUtilCore.findModuleForPsiElement(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -114,7 +111,8 @@ public abstract class RefElementImpl extends RefEntityImpl implements RefElement
|
||||
|
||||
@Override
|
||||
public RefModule getModule() {
|
||||
return myManager.getRefModule(myModule);
|
||||
final RefEntity owner = getOwner();
|
||||
return owner instanceof RefElement ? ((RefElement)owner).getModule() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,15 +21,14 @@ import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.util.JDOMExternalizerUtil;
|
||||
import com.intellij.openapi.util.NullableLazyValue;
|
||||
import com.intellij.openapi.util.VolatileNullableLazyValue;
|
||||
import com.intellij.util.ConcurrencyUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
@@ -38,7 +37,7 @@ import java.util.concurrent.ConcurrentMap;
|
||||
* A type of item with a distinct highlighting in an editor or in other views.
|
||||
*/
|
||||
public final class TextAttributesKey implements Comparable<TextAttributesKey> {
|
||||
private static final Logger LOG = Logger.getInstance("#" + TextAttributesKey.class.getName());
|
||||
private static final Logger LOG = Logger.getInstance(TextAttributesKey.class);
|
||||
|
||||
private static final TextAttributes NULL_ATTRIBUTES = new TextAttributes();
|
||||
private static final ConcurrentMap<String, TextAttributesKey> ourRegistry = ContainerUtil.newConcurrentMap();
|
||||
@@ -69,7 +68,14 @@ public final class TextAttributesKey implements Comparable<TextAttributesKey> {
|
||||
|
||||
@NotNull
|
||||
public static TextAttributesKey find(@NotNull @NonNls String externalName) {
|
||||
return ConcurrencyUtil.cacheOrGet(ourRegistry, externalName, new TextAttributesKey(externalName));
|
||||
TextAttributesKey v = ourRegistry.get(externalName);
|
||||
if (v != null) {
|
||||
return v;
|
||||
}
|
||||
|
||||
v = new TextAttributesKey(externalName);
|
||||
TextAttributesKey prev = ourRegistry.putIfAbsent(externalName, v);
|
||||
return prev == null ? v : prev;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
@@ -182,14 +188,15 @@ public final class TextAttributesKey implements Comparable<TextAttributesKey> {
|
||||
return key;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TextAttributesKey getFallbackAttributeKey() {
|
||||
return myFallbackAttributeKey;
|
||||
}
|
||||
|
||||
public void setFallbackAttributeKey(TextAttributesKey fallbackAttributeKey) {
|
||||
public void setFallbackAttributeKey(@Nullable TextAttributesKey fallbackAttributeKey) {
|
||||
myFallbackAttributeKey = fallbackAttributeKey;
|
||||
if (fallbackAttributeKey != null) {
|
||||
checkDependencies(fallbackAttributeKey, new HashSet<TextAttributesKey>());
|
||||
checkDependencies(fallbackAttributeKey, new THashSet<TextAttributesKey>());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -204,33 +211,30 @@ public final class TextAttributesKey implements Comparable<TextAttributesKey> {
|
||||
TextAttributes getDefaultAttributes(TextAttributesKey key);
|
||||
}
|
||||
|
||||
private void checkDependencies(@Nullable TextAttributesKey key, Set<TextAttributesKey> referencedKeys) {
|
||||
if (key != null) {
|
||||
if (!referencedKeys.contains(key)) {
|
||||
referencedKeys.add(key);
|
||||
TextAttributesKey fallbackKey = key.getFallbackAttributeKey();
|
||||
if (fallbackKey != null) {
|
||||
checkDependencies(fallbackKey, referencedKeys);
|
||||
}
|
||||
}
|
||||
else {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Cyclic TextAttributesKey dependency found: ");
|
||||
printDependencyLoop(sb, key);
|
||||
myFallbackAttributeKey = null;
|
||||
LOG.error(sb.toString());
|
||||
private void checkDependencies(@NotNull TextAttributesKey key, @NotNull Set<TextAttributesKey> referencedKeys) {
|
||||
if (referencedKeys.add(key)) {
|
||||
TextAttributesKey fallbackKey = key.getFallbackAttributeKey();
|
||||
if (fallbackKey != null) {
|
||||
checkDependencies(fallbackKey, referencedKeys);
|
||||
}
|
||||
}
|
||||
else {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append("Cyclic TextAttributesKey dependency found: ");
|
||||
printDependencyLoop(sb, key);
|
||||
myFallbackAttributeKey = null;
|
||||
LOG.error(sb.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private void printDependencyLoop(@NotNull StringBuilder stringBuilder,
|
||||
@NotNull TextAttributesKey currNode) {
|
||||
private void printDependencyLoop(@NotNull StringBuilder stringBuilder, @NotNull TextAttributesKey currNode) {
|
||||
stringBuilder.append(currNode.getExternalName()).append("->");
|
||||
TextAttributesKey fallbackKey = currNode.getFallbackAttributeKey();
|
||||
if (fallbackKey == this) {
|
||||
stringBuilder.append(getExternalName());
|
||||
return;
|
||||
}
|
||||
printDependencyLoop(stringBuilder, fallbackKey);
|
||||
else if (fallbackKey != null) {
|
||||
printDependencyLoop(stringBuilder, fallbackKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
package com.intellij.openapi.editor.markup;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
import org.intellij.lang.annotations.JdkConstants;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
@@ -32,8 +31,7 @@ public class TextAttributes implements Cloneable {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.markup.TextAttributes");
|
||||
|
||||
public static final TextAttributes ERASE_MARKER = new TextAttributes();
|
||||
|
||||
private boolean myEnforceEmpty;
|
||||
public static final TextAttributes USE_INHERITED_MARKER = new TextAttributes();
|
||||
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@NotNull
|
||||
@@ -71,9 +69,8 @@ public class TextAttributes implements Cloneable {
|
||||
this(null, null, null, EffectType.BOXED, Font.PLAIN);
|
||||
}
|
||||
|
||||
private TextAttributes(@NotNull AttributesFlyweight attributesFlyweight, boolean enforced) {
|
||||
private TextAttributes(@NotNull AttributesFlyweight attributesFlyweight) {
|
||||
myAttrs = attributesFlyweight;
|
||||
myEnforceEmpty = enforced;
|
||||
}
|
||||
|
||||
public TextAttributes(@NotNull Element element) {
|
||||
@@ -97,14 +94,6 @@ public class TextAttributes implements Cloneable {
|
||||
return getForegroundColor() == null && getBackgroundColor() == null && getEffectColor() == null && getFontType() == Font.PLAIN;
|
||||
}
|
||||
|
||||
public boolean isFallbackEnabled() {
|
||||
return isEmpty() && !myEnforceEmpty;
|
||||
}
|
||||
|
||||
public boolean containsValue() {
|
||||
return !isEmpty() || myEnforceEmpty;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
setForegroundColor(null);
|
||||
setBackgroundColor(null);
|
||||
@@ -179,7 +168,7 @@ public class TextAttributes implements Cloneable {
|
||||
|
||||
@Override
|
||||
public TextAttributes clone() {
|
||||
return new TextAttributes(myAttrs, myEnforceEmpty);
|
||||
return new TextAttributes(myAttrs);
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
@@ -194,17 +183,8 @@ public class TextAttributes implements Cloneable {
|
||||
return myAttrs.hashCode();
|
||||
}
|
||||
|
||||
public void readExternal(Element element) {
|
||||
try {
|
||||
myAttrs = AttributesFlyweight.create(element);
|
||||
}
|
||||
catch (InvalidDataException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
if (isEmpty()) {
|
||||
myEnforceEmpty = true;
|
||||
}
|
||||
public void readExternal(@NotNull Element element) {
|
||||
myAttrs = AttributesFlyweight.create(element);
|
||||
}
|
||||
|
||||
public void writeExternal(Element element) {
|
||||
@@ -216,17 +196,4 @@ public class TextAttributes implements Cloneable {
|
||||
return "[" + getForegroundColor() + "," + getBackgroundColor() + "," + getFontType() + "," + getEffectType() + "," +
|
||||
getEffectColor() + "," + getErrorStripeColor() + "]";
|
||||
}
|
||||
|
||||
/**
|
||||
* Enforces empty attributes instead of treating empty values as undefined.
|
||||
*
|
||||
* @param enforceEmpty True if empty values should be used as is (fallback is disabled).
|
||||
*/
|
||||
public void setEnforceEmpty(boolean enforceEmpty) {
|
||||
myEnforceEmpty = enforceEmpty;
|
||||
}
|
||||
|
||||
public boolean isEnforceEmpty() {
|
||||
return myEnforceEmpty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,7 @@ import java.util.List;
|
||||
|
||||
import static com.intellij.openapi.editor.colors.CodeInsightColors.*;
|
||||
import static com.intellij.openapi.editor.colors.EditorColors.*;
|
||||
import static com.intellij.openapi.editor.markup.TextAttributes.USE_INHERITED_MARKER;
|
||||
import static com.intellij.openapi.util.Couple.of;
|
||||
import static com.intellij.ui.ColorUtil.fromHex;
|
||||
|
||||
@@ -79,7 +80,7 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial
|
||||
private int myVersion = CURR_VERSION;
|
||||
|
||||
protected Map<ColorKey, Color> myColorsMap = ContainerUtilRt.newHashMap();
|
||||
protected Map<TextAttributesKey, TextAttributes> myAttributesMap = ContainerUtilRt.newHashMap();
|
||||
protected Map<TextAttributesKey, TextAttributes> myAttributesMap = new THashMap<>();
|
||||
|
||||
@NonNls private static final String EDITOR_FONT = "font";
|
||||
@NonNls private static final String CONSOLE_FONT = "console-font";
|
||||
@@ -180,7 +181,7 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial
|
||||
newScheme.setFont(type, font);
|
||||
}
|
||||
|
||||
newScheme.myAttributesMap = new HashMap<>(myAttributesMap);
|
||||
newScheme.myAttributesMap = new THashMap<>(myAttributesMap);
|
||||
newScheme.myColorsMap = new HashMap<>(myColorsMap);
|
||||
newScheme.myVersion = myVersion;
|
||||
}
|
||||
@@ -403,14 +404,16 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial
|
||||
|
||||
public void readAttributes(@NotNull Element childNode) {
|
||||
for (Element e : childNode.getChildren(OPTION_ELEMENT)) {
|
||||
TextAttributesKey key = TextAttributesKey.find(e.getAttributeValue(NAME_ATTR));
|
||||
Element valueElement = e.getChild(VALUE_ELEMENT);
|
||||
TextAttributes attr = myValueReader.read(TextAttributes.class, valueElement);
|
||||
String baseKeyName = e.getAttributeValue(BASE_ATTRIBUTES_ATTR);
|
||||
if (baseKeyName != null) {
|
||||
// For now inheritance overriding is not supported, just make sure that empty attributes mean inheritance.
|
||||
attr.setEnforceEmpty(false);
|
||||
TextAttributesKey key = TextAttributesKey.find(e.getAttributeValue(NAME_ATTR));
|
||||
if (valueElement == null) {
|
||||
if (e.getAttributeValue(BASE_ATTRIBUTES_ATTR) != null) {
|
||||
myAttributesMap.put(key, USE_INHERITED_MARKER);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
TextAttributes attr = myValueReader.read(TextAttributes.class, valueElement);
|
||||
myAttributesMap.put(key, attr);
|
||||
migrateErrorStripeColorFrom14(key, attr);
|
||||
}
|
||||
@@ -623,24 +626,54 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial
|
||||
private void writeAttributes(@NotNull Element attrElements) throws WriteExternalException {
|
||||
List<TextAttributesKey> list = new ArrayList<>(myAttributesMap.keySet());
|
||||
list.sort(null);
|
||||
for (TextAttributesKey key: list) {
|
||||
TextAttributes defaultAttr = myParentScheme != null ? myParentScheme.getAttributes(key) : new TextAttributes();
|
||||
for (TextAttributesKey key : list) {
|
||||
TextAttributes attributes = myAttributesMap.get(key);
|
||||
TextAttributesKey baseKey = key.getFallbackAttributeKey();
|
||||
TextAttributes defaultFallbackAttr =
|
||||
baseKey != null && myParentScheme instanceof AbstractColorsScheme ?
|
||||
((AbstractColorsScheme)myParentScheme).getFallbackAttributes(baseKey) : null;
|
||||
TextAttributes value = myAttributesMap.get(key);
|
||||
if (baseKey != null && value.isFallbackEnabled()) {
|
||||
if (isParentOverwritingInheritance(key)) {
|
||||
attrElements.addContent(new Element(OPTION_ELEMENT).setAttribute(NAME_ATTR, key.getExternalName()).setAttribute(BASE_ATTRIBUTES_ATTR, baseKey.getExternalName()));
|
||||
if (attributes == USE_INHERITED_MARKER) {
|
||||
if (baseKey != null) {
|
||||
attrElements.addContent(new Element(OPTION_ELEMENT)
|
||||
.setAttribute(NAME_ATTR, key.getExternalName())
|
||||
.setAttribute(BASE_ATTRIBUTES_ATTR, baseKey.getExternalName()));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (myParentScheme != null) {
|
||||
// fallback attributes must be not used, otherwise derived scheme as copy will not have such ke
|
||||
TextAttributes parentAttributes = myParentScheme instanceof AbstractColorsScheme
|
||||
? ((AbstractColorsScheme)myParentScheme).getDirectlyDefinedAttributes(key)
|
||||
: myParentScheme.getAttributes(key);
|
||||
if (parentAttributes != null && attributes.equals(parentAttributes)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (value.containsValue() && !value.equals(defaultAttr) || defaultAttr == defaultFallbackAttr) {
|
||||
Element valueElement = new Element(VALUE_ELEMENT);
|
||||
value.writeExternal(valueElement);
|
||||
attrElements.addContent(new Element(OPTION_ELEMENT).setAttribute(NAME_ATTR, key.getExternalName()).addContent(valueElement));
|
||||
|
||||
Element valueElement = new Element(VALUE_ELEMENT);
|
||||
attributes.writeExternal(valueElement);
|
||||
attrElements.addContent(new Element(OPTION_ELEMENT).setAttribute(NAME_ATTR, key.getExternalName()).addContent(valueElement));
|
||||
}
|
||||
}
|
||||
|
||||
public void optimizeAttributeMap() {
|
||||
EditorColorsScheme parentScheme = myParentScheme;
|
||||
if (parentScheme == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (TextAttributesKey key : new ArrayList<>(myAttributesMap.keySet())) {
|
||||
TextAttributes attributes = myAttributesMap.get(key);
|
||||
if (attributes == USE_INHERITED_MARKER) {
|
||||
if (key.getFallbackAttributeKey() == null) {
|
||||
myAttributesMap.remove(key);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
TextAttributes parentAttributes = parentScheme instanceof DefaultColorsScheme
|
||||
? ((DefaultColorsScheme)parentScheme).getAttributes(key, false)
|
||||
: parentScheme.getAttributes(key);
|
||||
if (Comparing.equal(parentAttributes, attributes)) {
|
||||
myAttributesMap.remove(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -661,15 +694,6 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial
|
||||
return metaInfoElement;
|
||||
}
|
||||
|
||||
private boolean isParentOverwritingInheritance(@NotNull TextAttributesKey key) {
|
||||
TextAttributes parentAttrs =
|
||||
myParentScheme instanceof AbstractColorsScheme ? ((AbstractColorsScheme)myParentScheme).getDirectlyDefinedAttributes(key) : null;
|
||||
if (parentAttrs != null) {
|
||||
return !parentAttrs.isFallbackEnabled();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected Color getOwnColor(ColorKey key) {
|
||||
return myColorsMap.get(key);
|
||||
}
|
||||
@@ -698,7 +722,6 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -756,15 +779,13 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial
|
||||
myConsoleLineSpacing = lineSpacing;
|
||||
}
|
||||
|
||||
protected TextAttributes getFallbackAttributes(TextAttributesKey fallbackKey) {
|
||||
if (fallbackKey == null) return null;
|
||||
protected TextAttributes getFallbackAttributes(@NotNull TextAttributesKey fallbackKey) {
|
||||
TextAttributes fallbackAttributes = getDirectlyDefinedAttributes(fallbackKey);
|
||||
if (fallbackAttributes != null) {
|
||||
if (!fallbackAttributes.isFallbackEnabled() || fallbackKey.getFallbackAttributeKey() == null) {
|
||||
return fallbackAttributes;
|
||||
}
|
||||
TextAttributesKey fallbackKeyFallbackKey = fallbackKey.getFallbackAttributeKey();
|
||||
if (fallbackAttributes != null && (fallbackAttributes != USE_INHERITED_MARKER || fallbackKeyFallbackKey == null)) {
|
||||
return fallbackAttributes;
|
||||
}
|
||||
return getFallbackAttributes(fallbackKey.getFallbackAttributeKey());
|
||||
return fallbackKeyFallbackKey == null ? null : getFallbackAttributes(fallbackKeyFallbackKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -782,10 +803,6 @@ public abstract class AbstractColorsScheme implements EditorColorsScheme, Serial
|
||||
return myParentScheme instanceof AbstractColorsScheme ? ((AbstractColorsScheme)myParentScheme).getDirectlyDefinedAttributes(key) : null;
|
||||
}
|
||||
|
||||
protected static boolean containsValue(@Nullable TextAttributes attributes) {
|
||||
return attributes != null && attributes.containsValue();
|
||||
}
|
||||
|
||||
public boolean isSaveNeeded() {
|
||||
return myIsSaveNeeded;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.intellij.openapi.editor.colors.impl;
|
||||
|
||||
import com.intellij.openapi.editor.colors.ColorKey;
|
||||
@@ -37,14 +36,23 @@ public class DefaultColorsScheme extends AbstractColorsScheme implements ReadOnl
|
||||
@Override
|
||||
@Nullable
|
||||
public TextAttributes getAttributes(TextAttributesKey key) {
|
||||
if (key == null) return null;
|
||||
return key == null ? null : getAttributes(key, true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TextAttributes getAttributes(@NotNull TextAttributesKey key, boolean isUseDefault) {
|
||||
TextAttributes attrs = myAttributesMap.get(key);
|
||||
if (attrs == null) {
|
||||
if (key.getFallbackAttributeKey() != null) {
|
||||
attrs = getFallbackAttributes(key.getFallbackAttributeKey());
|
||||
if (attrs != null && !attrs.isFallbackEnabled()) return attrs;
|
||||
if (attrs != null && attrs != TextAttributes.USE_INHERITED_MARKER) {
|
||||
return attrs;
|
||||
}
|
||||
}
|
||||
|
||||
if (isUseDefault) {
|
||||
attrs = getKeyDefaults(key);
|
||||
}
|
||||
attrs = getKeyDefaults(key);
|
||||
}
|
||||
return attrs;
|
||||
}
|
||||
|
||||
@@ -26,6 +26,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
import static com.intellij.openapi.editor.markup.TextAttributes.USE_INHERITED_MARKER;
|
||||
|
||||
public class EditorColorsSchemeImpl extends AbstractColorsScheme implements ExternalizableScheme {
|
||||
public EditorColorsSchemeImpl(EditorColorsScheme parentScheme) {
|
||||
super(parentScheme);
|
||||
@@ -33,7 +35,7 @@ public class EditorColorsSchemeImpl extends AbstractColorsScheme implements Exte
|
||||
|
||||
@Override
|
||||
public void setAttributes(@NotNull TextAttributesKey key, TextAttributes attributes) {
|
||||
if (!attributes.equals(getAttributes(key))) {
|
||||
if (attributes == USE_INHERITED_MARKER || !attributes.equals(getAttributes(key))) {
|
||||
myAttributesMap.put(key, attributes);
|
||||
}
|
||||
}
|
||||
@@ -47,30 +49,24 @@ public class EditorColorsSchemeImpl extends AbstractColorsScheme implements Exte
|
||||
|
||||
@Override
|
||||
public TextAttributes getAttributes(@Nullable TextAttributesKey key) {
|
||||
TextAttributes attributes = key == null ? null : getOwnAttributes(key);
|
||||
return attributes == null ? myParentScheme.getAttributes(key) : attributes;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private TextAttributes getOwnAttributes(@NotNull TextAttributesKey key) {
|
||||
TextAttributesKey fallbackKey = key.getFallbackAttributeKey();
|
||||
TextAttributes attributes = getDirectlyDefinedAttributes(key);
|
||||
if (fallbackKey == null) {
|
||||
if (containsValue(attributes)) {
|
||||
if (key != null) {
|
||||
TextAttributesKey fallbackKey = key.getFallbackAttributeKey();
|
||||
TextAttributes attributes = getDirectlyDefinedAttributes(key);
|
||||
if (fallbackKey == null) {
|
||||
return attributes;
|
||||
}
|
||||
else {
|
||||
if (attributes != null && attributes != USE_INHERITED_MARKER) {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
attributes = getFallbackAttributes(fallbackKey);
|
||||
if (attributes != null) {
|
||||
return attributes;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (containsValue(attributes) && !attributes.isFallbackEnabled()) {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
attributes = getFallbackAttributes(fallbackKey);
|
||||
if (containsValue(attributes)) {
|
||||
return attributes;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return myParentScheme.getAttributes(key);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -53,25 +53,22 @@ class TextAttributesReader extends ValueElementReader {
|
||||
*/
|
||||
@Override
|
||||
public <T> T read(Class<T> type, Element element) {
|
||||
if (TextAttributes.class.equals(type)) {
|
||||
TextAttributes attributes = new TextAttributes();
|
||||
if (element != null) {
|
||||
attributes.setAttributes(
|
||||
readChild(Color.class, element, FOREGROUND),
|
||||
readChild(Color.class, element, BACKGROUND),
|
||||
readChild(Color.class, element, EFFECT_COLOR),
|
||||
readChild(Color.class, element, ERROR_STRIPE),
|
||||
Effect.read(this, element),
|
||||
FontStyle.read(this, element));
|
||||
// needed for compatibility with TextAttributes(Element)
|
||||
if (attributes.isEmpty()) {
|
||||
attributes.setEnforceEmpty(true);
|
||||
}
|
||||
}
|
||||
//noinspection unchecked
|
||||
return (T)attributes;
|
||||
if (!TextAttributes.class.equals(type)) {
|
||||
return super.read(type, element);
|
||||
}
|
||||
return super.read(type, element);
|
||||
|
||||
TextAttributes attributes = new TextAttributes();
|
||||
if (element != null) {
|
||||
attributes.setAttributes(
|
||||
readChild(Color.class, element, FOREGROUND),
|
||||
readChild(Color.class, element, BACKGROUND),
|
||||
readChild(Color.class, element, EFFECT_COLOR),
|
||||
readChild(Color.class, element, ERROR_STRIPE),
|
||||
Effect.read(this, element),
|
||||
FontStyle.read(this, element));
|
||||
}
|
||||
//noinspection unchecked
|
||||
return (T)attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
|
Before Width: | Height: | Size: 347 B After Width: | Height: | Size: 181 B |
@@ -0,0 +1,11 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<title>threads</title>
|
||||
<g>
|
||||
<rect x="3.00107" y="4.8" width="9.99893" height="1.2" rx="0.6" ry="0.6" fill="#9aa7b0" opacity="0.7"/>
|
||||
<rect x="3.00107" y="8.7998" width="9.99893" height="1.2" rx="0.6" ry="0.6" fill="#9aa7b0" opacity="0.7"/>
|
||||
<rect x="3.00107" y="10.8" width="9.99893" height="1.2" rx="0.6" ry="0.6" fill="#9aa7b0" opacity="0.7"/>
|
||||
<path d="M13.991,1.82861a0.32754,0.32754,0,0,0-.2367-0.32129,3.83122,3.83122,0,0,0-.83088-0.207,26.9423,26.9423,0,0,0-3.09559-.26123C9.22708,1.0166,8.62608,1.01953,8.09984,1L8,1.002,7.90016,1c-0.52624.01953-1.12724,0.0166-1.728,0.03906a26.9423,26.9423,0,0,0-3.09559.26123,3.83122,3.83122,0,0,0-.83088.207,0.32754,0.32754,0,0,0-.2367.32129,5.715,5.715,0,0,0,.00438.70166A2.34713,2.34713,0,0,0,3.98172,4C4.64871,3.98535,6.34067,3.97852,8,3.97852S11.35129,3.98535,12.01828,4a2.34713,2.34713,0,0,0,1.96835-1.46973A5.715,5.715,0,0,0,13.991,1.82861ZM8.0151,2.43945L8,2.439l-0.0151.00049c-1.41654,0-2.565-.21826-2.565-0.4873A1.293,1.293,0,0,1,6.45927,1.562l0.02143-.00439,0.0095-.00049a10.23432,10.23432,0,0,1,1.02862-.084c0.142-.00586.28418-0.00781,0.4264-0.0083L7.9849,1.46436,8,1.46484l0.0151-.00049L8.05479,1.46484c0.14221,0.00049.28443,0.00244,0.4264,0.0083a10.23432,10.23432,0,0,1,1.02862.084L9.5193,1.55762,9.54073,1.562a1.293,1.293,0,0,1,1.03933.39014C10.58007,2.22119,9.43164,2.43945,8.0151,2.43945Z" fill="#40b6e0"/>
|
||||
<path d="M13.98661,14.13333a2.34691,2.34691,0,0,0-1.9835-1.29122c-0.14118,0-3.90391.01887-3.9873,0.0193-0.08364-.00043-3.84636-0.0193-3.98755-0.0193a2.37927,2.37927,0,0,0-1.9995,1.29122,4.4036,4.4036,0,0,0-.00439.61624A0.26614,0.26614,0,0,0,2.2058,15H13.82559a0.25109,0.25109,0,0,0,.16541-0.25044A4.4036,4.4036,0,0,0,13.98661,14.13333Z" fill="#40b6e0"/>
|
||||
<path d="M14.44657,7.55537A2.71806,2.71806,0,0,0,13.26,6.87178a3.81489,3.81489,0,0,0-.869-0.06885L12.37635,6.8H3.59947a0.6001,0.6001,0,0,0,0,1.2002h8.77688c0.20746,0.00049.423,0,.61264,0a1.17855,1.17855,0,0,1,1.02683,1.08643c0.04042,0.4751-.03.69678,0,1.13721a0.50325,0.50325,0,0,0,.57233.59912c0.37033,0,.39558-0.46832.3985-0.59912C14.98665,10.22383,15.13445,8.27461,14.44657,7.55537Z" fill="#9aa7b0" opacity="0.7"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 595 B After Width: | Height: | Size: 295 B |
@@ -0,0 +1,11 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<title>threads@2x</title>
|
||||
<g>
|
||||
<rect x="6.00214" y="9.6" width="19.99786" height="2.4" rx="0.6" ry="0.6" fill="#9aa7b0" opacity="0.7"/>
|
||||
<rect x="6.00214" y="17.59961" width="19.99786" height="2.4" rx="0.6" ry="0.6" fill="#9aa7b0" opacity="0.7"/>
|
||||
<rect x="6.00214" y="21.6" width="19.99786" height="2.4" rx="0.6" ry="0.6" fill="#9aa7b0" opacity="0.7"/>
|
||||
<path d="M27.982,3.65723a0.65509,0.65509,0,0,0-.4734-0.64258,7.66244,7.66244,0,0,0-1.66176-.41406,53.8846,53.8846,0,0,0-6.19118-.52246C18.45417,2.0332,17.25217,2.03906,16.19968,2,16.1315,2.001,16.06818,2.00293,16,2.00391,15.93181,2.00293,15.8685,2.001,15.80031,2c-1.05248.03906-2.25448,0.0332-3.456,0.07813a53.8846,53.8846,0,0,0-6.19118.52246,7.66244,7.66244,0,0,0-1.66176.41406,0.65509,0.65509,0,0,0-.4734.64258,11.43,11.43,0,0,0,.00877,1.40332C4.08908,5.64941,5.77714,8.04785,7.96344,8,9.29743,7.9707,12.68134,7.957,16,7.957S22.70257,7.9707,24.03656,8c2.1863,0.04785,3.87436-2.35059,3.9367-2.93945A11.43,11.43,0,0,0,27.982,3.65723ZM16.0302,4.87891L16,4.87793l-0.0302.001c-2.83308,0-5.12994-.43652-5.12994-0.97461,0-.32129.82358-0.60254,2.07866-0.78027,0.01461-.00293.02874-0.00684,0.04286-0.00879l0.019-.001a20.46864,20.46864,0,0,1,2.05723-.168c0.28394-.01172.56837-0.01563,0.8528-0.0166,0.02679,0,.05211-0.001.07939-0.001L16,2.92969l0.0302-.001c0.02727,0,.0526.001,0.07939,0.001,0.28443,0.001.56886,0.00488,0.8528,0.0166a20.46864,20.46864,0,0,1,2.05723.168l0.019,0.001c0.01412,0.002.02825,0.00586,0.04286,0.00879,1.25509,0.17773,2.07866.459,2.07866,0.78027C21.16013,4.44238,18.86328,4.87891,16.0302,4.87891Z" fill="#40b6e0"/>
|
||||
<path d="M27.97323,28.26665a4.69382,4.69382,0,0,0-3.967-2.58244c-0.28237,0-7.80781.03774-7.9746,0.0386-0.16728-.00086-7.69272-0.0386-7.97509-0.0386a4.75855,4.75855,0,0,0-3.999,2.58244,8.8072,8.8072,0,0,0-.00878,1.23247A0.53227,0.53227,0,0,0,4.41159,30H27.65118a0.50218,0.50218,0,0,0,.33082-0.50088A8.8072,8.8072,0,0,0,27.97323,28.26665Z" fill="#40b6e0"/>
|
||||
<path d="M28.89314,15.11074A5.43613,5.43613,0,0,0,26.52,13.74355a7.62978,7.62978,0,0,0-1.73809-.1377c-0.01023,0-.01851-0.00586-0.02922-0.00586H7.19894a1.2002,1.2002,0,0,0,0,2.40039H24.7527c0.41492,0.001.84591,0,1.22528,0a2.3571,2.3571,0,0,1,2.05365,2.17285c0.08084,0.9502-.0599,1.39355,0,2.27441a1.00651,1.00651,0,0,0,1.14466,1.19824c0.74066,0,.79116-0.93665.797-1.19824C29.97329,20.44766,30.2689,16.54922,28.89314,15.11074Z" fill="#9aa7b0" opacity="0.7"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 145 B After Width: | Height: | Size: 113 B |
@@ -0,0 +1,7 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<title>any_type</title>
|
||||
<g>
|
||||
<polygon points="6 0 2 4 6 4 6 0" fill="#9aa7b0" opacity="0.7" style="isolation: isolate"/>
|
||||
<polygon points="7 0 7 4 7 5 6 5 2 5 2 15 13 15 13 0 7 0" fill="#9aa7b0" opacity="0.7" style="isolation: isolate"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 356 B |
|
Before Width: | Height: | Size: 190 B After Width: | Height: | Size: 153 B |
@@ -0,0 +1,7 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<title>any_type@2x</title>
|
||||
<g>
|
||||
<polygon points="12 0 4 8 12 8 12 0" fill="#9aa7b0" opacity="0.7" style="isolation: isolate"/>
|
||||
<polygon points="14 0 14 8 14 10 12 10 4 10 4 30 26 30 26 0 14 0" fill="#9aa7b0" opacity="0.7" style="isolation: isolate"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 370 B |
|
Before Width: | Height: | Size: 115 B After Width: | Height: | Size: 106 B |
@@ -0,0 +1,24 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<title>archive</title>
|
||||
<g>
|
||||
<g>
|
||||
<polygon points="5 0 2 0 2 5 2 15 5 15 5 0" fill="#9aa7b0" opacity="0.7" style="isolation: isolate"/>
|
||||
<rect x="10" width="3" height="15" fill="#9aa7b0" opacity="0.7" style="isolation: isolate"/>
|
||||
</g>
|
||||
<polygon points="7 2 5 2 6 3 8 3 7 2" fill="#40b6e0"/>
|
||||
<polygon points="7 0 5 0 6 1 8 1 7 0" fill="#40b6e0"/>
|
||||
<polygon points="7 8 5 8 6 9 8 9 7 8" fill="#40b6e0"/>
|
||||
<polygon points="7 10 5 10 6 11 8 11 7 10" fill="#40b6e0"/>
|
||||
<polygon points="7 12 5 12 6 13 8 13 7 12" fill="#40b6e0"/>
|
||||
<polygon points="7 14 5 14 6 15 8 15 7 14" fill="#40b6e0"/>
|
||||
<polygon points="7 4 5 4 6 5 8 5 7 4" fill="#40b6e0"/>
|
||||
<polygon points="7 6 5 6 6 7 8 7 7 6" fill="#40b6e0"/>
|
||||
<polygon points="8 3 10 3 9 4 7 4 8 3" fill="#40b6e0"/>
|
||||
<polygon points="8 1 10 1 9 2 7 2 8 1" fill="#40b6e0"/>
|
||||
<polygon points="8 9 10 9 9 10 7 10 8 9" fill="#40b6e0"/>
|
||||
<polygon points="8 11 10 11 9 12 7 12 8 11" fill="#40b6e0"/>
|
||||
<polygon points="8 13 10 13 9 14 7 14 8 13" fill="#40b6e0"/>
|
||||
<polygon points="8 5 10 5 9 6 7 6 8 5" fill="#40b6e0"/>
|
||||
<polygon points="8 7 10 7 9 8 7 8 8 7" fill="#40b6e0"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 158 B After Width: | Height: | Size: 149 B |
@@ -0,0 +1,24 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||
<title>archive@2x</title>
|
||||
<g>
|
||||
<g>
|
||||
<polygon points="10 0 4 0 4 10 4 30 10 30 10 0" fill="#9aa7b0" opacity="0.7" style="isolation: isolate"/>
|
||||
<rect x="20" width="6" height="30" fill="#9aa7b0" opacity="0.7" style="isolation: isolate"/>
|
||||
</g>
|
||||
<polygon points="14 4 10 4 12 6 16 6 14 4" fill="#40b6e0"/>
|
||||
<polygon points="14 0 10 0 12 2 16 2 14 0" fill="#40b6e0"/>
|
||||
<polygon points="14 16 10 16 12 18 16 18 14 16" fill="#40b6e0"/>
|
||||
<polygon points="14 20 10 20 12 22 16 22 14 20" fill="#40b6e0"/>
|
||||
<polygon points="14 24 10 24 12 26 16 26 14 24" fill="#40b6e0"/>
|
||||
<polygon points="14 28 10 28 12 30 16 30 14 28" fill="#40b6e0"/>
|
||||
<polygon points="14 8 10 8 12 10 16 10 14 8" fill="#40b6e0"/>
|
||||
<polygon points="14 12 10 12 12 14 16 14 14 12" fill="#40b6e0"/>
|
||||
<polygon points="16 6 20 6 18 8 14 8 16 6" fill="#40b6e0"/>
|
||||
<polygon points="16 2 20 2 18 4 14 4 16 2" fill="#40b6e0"/>
|
||||
<polygon points="16 18 20 18 18 20 14 20 16 18" fill="#40b6e0"/>
|
||||
<polygon points="16 22 20 22 18 24 14 24 16 22" fill="#40b6e0"/>
|
||||
<polygon points="16 26 20 26 18 28 14 28 16 26" fill="#40b6e0"/>
|
||||
<polygon points="16 10 20 10 18 12 14 12 16 10" fill="#40b6e0"/>
|
||||
<polygon points="16 14 20 14 18 16 14 16 16 14" fill="#40b6e0"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 205 B After Width: | Height: | Size: 225 B |
@@ -0,0 +1,12 @@
|
||||
<svg id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<title>as</title>
|
||||
<g>
|
||||
<g>
|
||||
<polygon points="6 0 2 4 6 4 6 0" fill="#9aa7b0" opacity="0.7" style="isolation: isolate"/>
|
||||
<polygon points="7 0 7 4 7 5 6 5 2 5 2 8 13 8 13 0 7 0" fill="#9aa7b0" opacity="0.7" style="isolation: isolate"/>
|
||||
</g>
|
||||
<rect x="1" y="9" width="15" height="7" fill="#f26522" opacity="0.6"/>
|
||||
<path d="M4.10964,10H4.89036L7,15H6.10941L5.62313,13.80111H3.35623L2.86326,15H2ZM5.3153,13.02841l-0.82869-1.986-0.822,1.986H5.3153Z" fill="#231f20" opacity="0.6"/>
|
||||
<path d="M10.257,12.11133c-1.05054-.22217-1.2995-0.38916-1.2995-0.76416V11.333a0.73775,0.73775,0,0,1,.88694-0.57617c0.00848,0,.012-0.00391.02-0.00439v0.00146h1.48964V10H9.95664l-0.00082.00684C9.923,10.00586,9.89344,10,9.85979,10A1.61237,1.61237,0,0,0,8,11.40967v0.01416c0,0.89551.65413,1.20117,1.81356,1.45117,1.01115,0.208,1.22892.396,1.22892,0.74316v0.01367a0.79588,0.79588,0,0,1-.96464.61084c-0.01614,0-.02982-0.00342-0.04569-0.00391v0.00684h-1.558v0.75391L10.033,14.998,10.05431,15C11.19841,15,12,14.4585,12,13.54883V13.53418C12,12.72949,11.40825,12.36133,10.257,12.11133Z" fill="#231f20" opacity="0.6"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 537 B After Width: | Height: | Size: 376 B |