mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -34,5 +34,9 @@ abstract class LinuxDistributionCustomizer {
|
||||
*/
|
||||
abstract String rootDirectoryName(String buildNumber)
|
||||
|
||||
/**
|
||||
* Override this method to copy additional files to Linux distribution of the product.
|
||||
* @param targetDirectory contents of this directory will be packed into .tar.gz archive under {@link #rootDirectoryName(java.lang.String)}
|
||||
*/
|
||||
void copyAdditionalFiles(BuildContext context, String targetDirectory) {}
|
||||
}
|
||||
|
||||
@@ -19,12 +19,24 @@ package org.jetbrains.intellij.build
|
||||
* @author nik
|
||||
*/
|
||||
abstract class MacDistributionCustomizer {
|
||||
/**
|
||||
* Path to icns file containing 32x32 product icon for Mac OS distribution
|
||||
*/
|
||||
String icnsPath
|
||||
|
||||
/**
|
||||
* The minimum version of Mac OS where the product is allowed to be installed
|
||||
*/
|
||||
String minOSXVersion = "10.8"
|
||||
String helpId = ""
|
||||
String docTypes = null
|
||||
List<String> urlSchemes = []
|
||||
List<String> architectures = ["x86_64"]
|
||||
|
||||
/**
|
||||
* If {@code true} YourKit agent will be automatically attached when an EAP build of the product starts under Mac OS. This property is
|
||||
* taken into account only if {@link ProductProperties#enableYourkitAgentInEAP} is {@code true}.
|
||||
*/
|
||||
boolean enableYourkitAgentInEAP = true
|
||||
|
||||
/**
|
||||
|
||||
@@ -106,6 +106,10 @@ public abstract class ProductProperties {
|
||||
* directories of Windows, Linux and Mac OS distributions. If {@code null} no agent files will be bundled.
|
||||
*/
|
||||
String yourkitAgentBinariesDirectoryPath = null
|
||||
|
||||
/**
|
||||
* If {@code true} YourKit agent will be automatically attached when an EAP build of the product starts. It makes sense only if {@link #yourkitAgentBinariesDirectoryPath} is non-null.
|
||||
*/
|
||||
boolean enableYourkitAgentInEAP = false
|
||||
|
||||
List<String> excludedPlugins = []
|
||||
|
||||
@@ -54,6 +54,11 @@ abstract class WindowsDistributionCustomizer {
|
||||
*/
|
||||
abstract String rootDirectoryName(String buildNumber)
|
||||
|
||||
/**
|
||||
* Override this method to copy additional files to Windows distribution of the product.
|
||||
* @param targetDirectory contents of this directory will be packed into zip archive and exe installer, so when the product is installed
|
||||
* it'll be placed under its root directory.
|
||||
*/
|
||||
void copyAdditionalFiles(BuildContext context, String targetDirectory) {}
|
||||
|
||||
String uninstallFeedbackPageUrl(ApplicationInfoProperties applicationInfo) {
|
||||
|
||||
@@ -876,16 +876,14 @@ binding.setVariable("signExecutableFiles", { String binDir ->
|
||||
})
|
||||
|
||||
binding.setVariable("bundledJDKs"){
|
||||
bundledJDK(false, paths.sandbox)
|
||||
bundledJDK(false)
|
||||
}
|
||||
|
||||
binding.setVariable("bundledJDK64s"){
|
||||
bundledJDK(true, paths.sandbox)
|
||||
bundledJDK(true)
|
||||
}
|
||||
|
||||
binding.setVariable("prepareBundledJDKs", { String targetDir -> bundledJDK(false, targetDir)})
|
||||
|
||||
private bundledJDK(boolean win64, String targetDir) {
|
||||
private bundledJDK(boolean win64) {
|
||||
requireProperty("artifact.linux.no.jdk", "true")
|
||||
requireProperty("artifact.mac.no.jdk", "true")
|
||||
requireProperty("jdk.oracle.win", "jdk8u")
|
||||
@@ -897,11 +895,11 @@ private bundledJDK(boolean win64, String targetDir) {
|
||||
def jdkDir = new File("${home}/build/jdk/win")
|
||||
if (p("jdk.oracle.win") != "false" && (jdkDir.exists() && jdkDir.isDirectory())) {
|
||||
setProperty("winJDK", getPathToBundledJDK(jdkDir, p("jdk.oracle.win"), (win64 ? "x64.tar.gz": "x86.tar.gz")))
|
||||
extractRedistJre(winJDK, "$targetDir/jdk.oracle.win/jre")
|
||||
extractRedistJre(winJDK, "${paths.sandbox}/jdk.oracle.win/jre")
|
||||
}
|
||||
if (p("jdk.win") != "false" && (jdkDir.exists() && jdkDir.isDirectory())) {
|
||||
setProperty("winCustomJDKx32", getPathToBundledJDK(jdkDir, p("jdk.win"), (win64 ? "x64.tar.gz": "x86.tar.gz")))
|
||||
extractRedistJre(winCustomJDKx32, "$targetDir/jdk.win/jre")
|
||||
extractRedistJre(winCustomJDKx32, "${paths.sandbox}/jdk.win/jre")
|
||||
}
|
||||
jdkDir = new File("${home}/build/jdk/mac")
|
||||
if (p("jdk.mac") != "false" && (jdkDir.exists() && jdkDir.isDirectory())) {
|
||||
@@ -910,7 +908,7 @@ private bundledJDK(boolean win64, String targetDir) {
|
||||
jdkDir = new File("${home}/build/jdk/linux")
|
||||
if (p("jdk.linux") != "false" && (jdkDir.exists() && jdkDir.isDirectory())) {
|
||||
setProperty("linuxJDK", getPathToBundledJDK(jdkDir, p("jdk.linux"), ".tar.gz"))
|
||||
extractRedistJre(linuxJDK, "$targetDir/jdk.linux/jre")
|
||||
extractRedistJre(linuxJDK, "${paths.sandbox}/jdk.linux/jre")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-1
@@ -167,7 +167,15 @@ public class UnusedDeclarationPresentation extends DefaultInspectionToolPresenta
|
||||
|
||||
@Override
|
||||
public QuickFixAction[] getQuickFixes(@NotNull final RefEntity[] refElements, CommonProblemDescriptor[] allowedDescriptors) {
|
||||
return myQuickFixActions;
|
||||
boolean showFixes = false;
|
||||
for (RefEntity element : refElements) {
|
||||
if (!getIgnoredRefElements().contains(element) && element.isValid()) {
|
||||
showFixes = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return showFixes ? myQuickFixActions : QuickFixAction.EMPTY;
|
||||
}
|
||||
|
||||
final QuickFixAction[] myQuickFixActions;
|
||||
|
||||
@@ -223,7 +223,14 @@ open class StateStorageManagerImpl(private val rootTagName: String,
|
||||
throw IllegalArgumentException("Extension is missing for storage file: $filePath")
|
||||
}
|
||||
|
||||
val effectiveRoamingType = if (roamingType == RoamingType.DEFAULT && collapsedPath == StoragePathMacros.WORKSPACE_FILE) RoamingType.DISABLED else roamingType
|
||||
val effectiveRoamingType: RoamingType
|
||||
if (roamingType != RoamingType.DISABLED && (collapsedPath == StoragePathMacros.WORKSPACE_FILE || collapsedPath == "other.xml")) {
|
||||
effectiveRoamingType = RoamingType.DISABLED
|
||||
}
|
||||
else {
|
||||
effectiveRoamingType = roamingType
|
||||
}
|
||||
|
||||
val storage = createFileBasedStorage(filePath, collapsedPath, effectiveRoamingType)
|
||||
if (isUseVfsListener == ThreeState.YES && storage is StorageVirtualFileTracker.TrackedStorage) {
|
||||
virtualFileTracker?.put(filePath, storage)
|
||||
|
||||
@@ -663,6 +663,15 @@ public class VfsUtilCore {
|
||||
return components;
|
||||
}
|
||||
|
||||
public static boolean hasInvalidFiles(@NotNull Iterable<VirtualFile> files) {
|
||||
for (VirtualFile file : files) {
|
||||
if (!file.isValid()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* this collection will keep only distinct files/folders, e.g. C:\foo\bar will be removed when C:\foo is added
|
||||
*/
|
||||
|
||||
+1
-10
@@ -55,7 +55,7 @@ public class AdditionalIndexableFileSet implements IndexableFileSet {
|
||||
|
||||
private Set<VirtualFile> getDirectories() {
|
||||
Set<VirtualFile> directories = cachedDirectories;
|
||||
if (directories == null || filesInvalidated(directories) || filesInvalidated(cachedFiles)) {
|
||||
if (directories == null || VfsUtilCore.hasInvalidFiles(directories) || VfsUtilCore.hasInvalidFiles(cachedFiles)) {
|
||||
directories = collectFilesAndDirectories();
|
||||
}
|
||||
return directories;
|
||||
@@ -83,15 +83,6 @@ public class AdditionalIndexableFileSet implements IndexableFileSet {
|
||||
return directories;
|
||||
}
|
||||
|
||||
public static boolean filesInvalidated(Set<VirtualFile> files) {
|
||||
for (VirtualFile file : files) {
|
||||
if (!file.isValid()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInSet(@NotNull VirtualFile file) {
|
||||
return VfsUtilCore.isUnder(file, getDirectories()) || cachedFiles.contains(file);
|
||||
|
||||
+1
-11
@@ -19,7 +19,6 @@ import com.intellij.codeInspection.CommonProblemDescriptor;
|
||||
import com.intellij.codeInspection.ProblemDescriptorBase;
|
||||
import com.intellij.diff.tools.util.FoldingModelSupport;
|
||||
import com.intellij.diff.util.DiffDrawUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.FoldRegion;
|
||||
import com.intellij.openapi.editor.ScrollType;
|
||||
import com.intellij.openapi.editor.ex.DocumentEx;
|
||||
@@ -39,19 +38,10 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
public class ProblemPreviewEditorPresentation {
|
||||
private final static int VIEW_ADDITIONAL_OFFSET = 4;
|
||||
private final static Logger LOG = Logger.getInstance(ProblemPreviewEditorPresentation.class);
|
||||
|
||||
private final EditorEx myEditor;
|
||||
private final InspectionResultsView myView;
|
||||
private final SortedSet<PreviewEditorFoldingRegion> myFoldedRegions = new TreeSet<>(new Comparator<PreviewEditorFoldingRegion>() {
|
||||
@Override
|
||||
public int compare(PreviewEditorFoldingRegion r1, PreviewEditorFoldingRegion r2) {
|
||||
if (r1 == r2) return 0;
|
||||
final int diff = r1.startLine - r2.startLine;
|
||||
LOG.assertTrue(diff != 0);
|
||||
return diff;
|
||||
}
|
||||
});
|
||||
private final SortedSet<PreviewEditorFoldingRegion> myFoldedRegions = new TreeSet<>(Comparator.comparing(x -> x.startLine));
|
||||
private final DocumentEx myDocument;
|
||||
|
||||
public ProblemPreviewEditorPresentation(EditorEx editor, InspectionResultsView view) {
|
||||
|
||||
@@ -122,7 +122,7 @@ public class RefElementNode extends SuppressableInspectionTreeNode {
|
||||
|
||||
@Override
|
||||
public int getProblemCount(boolean allowSuppressed) {
|
||||
return isLeaf() ? myPresentation.getIgnoredRefElements().contains(getElement()) ? 0 : 1 : super.getProblemCount(allowSuppressed);
|
||||
return isLeaf() ? myPresentation.getIgnoredRefElements().contains(getElement()) && !(allowSuppressed && isAlreadySuppressedFromView() && isValid()) ? 0 : 1 : super.getProblemCount(allowSuppressed);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+12
-5
@@ -21,6 +21,7 @@ import com.intellij.codeInspection.ex.InspectionManagerEx;
|
||||
import com.intellij.codeInspection.ex.InspectionToolWrapper;
|
||||
import com.intellij.codeInspection.reference.RefElement;
|
||||
import com.intellij.codeInspection.reference.RefEntity;
|
||||
import com.intellij.codeInspection.ui.ProblemDescriptionNode;
|
||||
import com.intellij.codeInspection.ui.SuppressableInspectionTreeNode;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -38,6 +39,7 @@ import com.intellij.util.containers.Queue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -137,16 +139,19 @@ public class SuppressActionSequentialTask implements SequentialTask {
|
||||
}
|
||||
|
||||
final RefElement containerRef = refEntity.getRefManager().getReference(container);
|
||||
final Set<Object> suppressedNodes = myContext.getView().getSuppressedNodes(wrapper.getShortName());
|
||||
if (containerRef != null) {
|
||||
Queue<RefEntity> toIgnoreInView = new Queue<RefEntity>(1);
|
||||
toIgnoreInView.addLast(containerRef);
|
||||
while (!toIgnoreInView.isEmpty()) {
|
||||
final RefEntity entity = toIgnoreInView.pullFirst();
|
||||
final CommonProblemDescriptor[] descriptors = myContext.getPresentation(wrapper).getIgnoredElements().get(entity);
|
||||
if (descriptors != null) {
|
||||
for (CommonProblemDescriptor problemDescriptor : descriptors) {
|
||||
myContext.getView().getSuppressedNodes(wrapper.getShortName()).add(problemDescriptor);
|
||||
if (node instanceof ProblemDescriptionNode) {
|
||||
final CommonProblemDescriptor[] descriptors = myContext.getPresentation(wrapper).getIgnoredElements().get(entity);
|
||||
if (descriptors != null) {
|
||||
Collections.addAll(suppressedNodes, descriptors);
|
||||
}
|
||||
} else {
|
||||
suppressedNodes.add(entity);
|
||||
}
|
||||
final List<RefEntity> children = entity.getChildren();
|
||||
if (children != null) {
|
||||
@@ -156,7 +161,9 @@ public class SuppressActionSequentialTask implements SequentialTask {
|
||||
}
|
||||
}
|
||||
}
|
||||
myContext.getView().getSuppressedNodes(wrapper.getShortName()).add(descriptor);
|
||||
if (node instanceof ProblemDescriptionNode) {
|
||||
suppressedNodes.add(descriptor);
|
||||
}
|
||||
}
|
||||
catch (IncorrectOperationException e1) {
|
||||
LOG.error(e1);
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.lang.LanguageUtil;
|
||||
import com.intellij.lang.PerFileMappings;
|
||||
import com.intellij.lang.PerFileMappingsBase;
|
||||
import com.intellij.openapi.application.AccessToken;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.components.PersistentStateComponent;
|
||||
@@ -44,14 +45,14 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileWithId;
|
||||
import com.intellij.psi.LanguageSubstitutor;
|
||||
import com.intellij.psi.LanguageSubstitutors;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import com.intellij.util.PairConsumer;
|
||||
import com.intellij.util.PathUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.indexing.IndexableSetContributor;
|
||||
import com.intellij.util.indexing.LightDirectoryIndex;
|
||||
import com.intellij.util.messages.MessageBus;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -59,9 +60,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
@State(name = "ScratchFileService", storages = @Storage("scratches.xml"))
|
||||
@@ -72,22 +71,14 @@ public class ScratchFileServiceImpl extends ScratchFileService implements Persis
|
||||
private final LightDirectoryIndex<RootType> myIndex;
|
||||
private final MyLanguages myScratchMapping = new MyLanguages();
|
||||
|
||||
protected ScratchFileServiceImpl(MessageBus messageBus) {
|
||||
myIndex = new LightDirectoryIndex<RootType>(messageBus.connect(), NULL_TYPE) {
|
||||
|
||||
@Override
|
||||
protected void collectRoots(@NotNull PairConsumer<VirtualFile, RootType> consumer) {
|
||||
LocalFileSystem fileSystem = LocalFileSystem.getInstance();
|
||||
for (RootType r : RootType.getAllRootIds()) {
|
||||
String root = getRootPath(r);
|
||||
VirtualFile rootFile = fileSystem.findFileByPath(root);
|
||||
if (rootFile != null) {
|
||||
consumer.consume(rootFile, r);
|
||||
}
|
||||
}
|
||||
protected ScratchFileServiceImpl(Application application) {
|
||||
myIndex = new LightDirectoryIndex<RootType>(application, NULL_TYPE, index -> {
|
||||
LocalFileSystem fileSystem = LocalFileSystem.getInstance();
|
||||
for (RootType r : RootType.getAllRootIds()) {
|
||||
index.putInfo(fileSystem.findFileByPath(getRootPath(r)), r);
|
||||
}
|
||||
};
|
||||
initFileOpenedListener(messageBus);
|
||||
});
|
||||
initFileOpenedListener(application.getMessageBus());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -101,7 +92,6 @@ public class ScratchFileServiceImpl extends ScratchFileService implements Persis
|
||||
public RootType getRootType(@Nullable VirtualFile file) {
|
||||
if (file == null) return null;
|
||||
VirtualFile directory = file.isDirectory() ? file : file.getParent();
|
||||
if (!(directory instanceof VirtualFileWithId)) return null;
|
||||
RootType result = myIndex.getInfoForFile(directory);
|
||||
return result == NULL_TYPE ? null : result;
|
||||
}
|
||||
@@ -314,4 +304,26 @@ public class ScratchFileServiceImpl extends ScratchFileService implements Persis
|
||||
private static Language getLanguageByFileName(@Nullable VirtualFile file) {
|
||||
return file == null ? null : LanguageUtil.getFileTypeLanguage(FileTypeManager.getInstance().getFileTypeByFileName(file.getName()));
|
||||
}
|
||||
|
||||
public static class IndexSetContributor extends IndexableSetContributor {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<VirtualFile> getAdditionalRootsToIndex() {
|
||||
ScratchFileService instance = ScratchFileService.getInstance();
|
||||
LocalFileSystem fileSystem = LocalFileSystem.getInstance();
|
||||
HashSet<VirtualFile> result = ContainerUtil.newHashSet();
|
||||
for (RootType rootType : RootType.getAllRootIds()) {
|
||||
if (rootType.isHidden()) continue;
|
||||
ContainerUtil.addIfNotNull(result, fileSystem.findFileByPath(instance.getRootPath(rootType)));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<VirtualFile> getAdditionalProjectRootsToIndex(@NotNull Project project) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
}
|
||||
+10
-4
@@ -42,6 +42,7 @@ import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.ui.ReplacePromptDialog;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -49,7 +50,7 @@ import java.util.*;
|
||||
* @author Dennis.Ushakov
|
||||
*/
|
||||
public class ExtractMethodHelper {
|
||||
public static void processDuplicates(@NotNull final PsiElement callElement,
|
||||
public static void processDuplicates(@Nullable final PsiElement callElement,
|
||||
@NotNull final PsiElement generatedMethod,
|
||||
@NotNull final List<PsiElement> scope,
|
||||
@NotNull final SimpleDuplicatesFinder finder,
|
||||
@@ -60,7 +61,7 @@ public class ExtractMethodHelper {
|
||||
replaceDuplicates(callElement, editor, replacer, finder.findDuplicates(scope, generatedMethod));
|
||||
return;
|
||||
}
|
||||
final Project project = callElement.getProject();
|
||||
final Project project = generatedMethod.getProject();
|
||||
ProgressManager.getInstance().run(new Task.Backgroundable(project, RefactoringBundle.message("searching.for.duplicates"), true) {
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
if (myProject == null || myProject.isDisposed()) return;
|
||||
@@ -115,7 +116,7 @@ public class ExtractMethodHelper {
|
||||
* @param duplicates discovered duplicates of extracted code fragment
|
||||
* @see #collectDuplicates(SimpleDuplicatesFinder, List, PsiElement)
|
||||
*/
|
||||
public static void replaceDuplicates(@NotNull PsiElement callElement,
|
||||
public static void replaceDuplicates(@Nullable PsiElement callElement,
|
||||
@NotNull Editor editor,
|
||||
@NotNull Consumer<Pair<SimpleMatch, PsiElement>> replacer,
|
||||
@NotNull List<SimpleMatch> duplicates) {
|
||||
@@ -124,7 +125,12 @@ public class ExtractMethodHelper {
|
||||
.message("0.has.detected.1.code.fragments.in.this.file.that.can.be.replaced.with.a.call.to.extracted.method",
|
||||
ApplicationNamesInfo.getInstance().getProductName(), duplicates.size());
|
||||
final boolean isUnittest = ApplicationManager.getApplication().isUnitTestMode();
|
||||
final Project project = callElement.getProject();
|
||||
final Project project = callElement != null ? callElement.getProject() : editor.getProject();
|
||||
if (project == null) {
|
||||
Messages.showErrorDialog(editor.getComponent(), "Cannot find project.");
|
||||
return;
|
||||
}
|
||||
|
||||
final int exitCode = !isUnittest ? Messages.showYesNoDialog(project, message,
|
||||
RefactoringBundle.message("refactoring.extract.method.dialog.title"),
|
||||
Messages.getInformationIcon()) :
|
||||
|
||||
+24
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -13,8 +13,10 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.ide.scratch;
|
||||
package com.intellij.util.indexing;
|
||||
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.fileTypes.FileTypeEvent;
|
||||
import com.intellij.openapi.fileTypes.FileTypeListener;
|
||||
import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
@@ -23,7 +25,7 @@ import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.openapi.vfs.VirtualFileWithId;
|
||||
import com.intellij.openapi.vfs.newvfs.BulkFileListener;
|
||||
import com.intellij.openapi.vfs.newvfs.events.VFileEvent;
|
||||
import com.intellij.util.PairConsumer;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.containers.ConcurrentIntObjectMap;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
@@ -33,23 +35,27 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This is a light version of DirectoryIndexImpl.
|
||||
* This is a light version of DirectoryIndexImpl
|
||||
*
|
||||
* @author gregsh
|
||||
*/
|
||||
abstract class LightDirectoryIndex<T> {
|
||||
public final class LightDirectoryIndex<T> {
|
||||
private final ConcurrentIntObjectMap<T> myInfoCache = ContainerUtil.createConcurrentIntObjectMap();
|
||||
private final T myDefValue;
|
||||
private final Consumer<LightDirectoryIndex<T>> myInitializer;
|
||||
|
||||
public LightDirectoryIndex(@NotNull MessageBusConnection connection, @NotNull T defValue) {
|
||||
public LightDirectoryIndex(@NotNull Disposable parentDisposable, @NotNull T defValue, @NotNull Consumer<LightDirectoryIndex<T>> initializer) {
|
||||
myDefValue = defValue;
|
||||
reinitRoots();
|
||||
myInitializer = initializer;
|
||||
resetIndex();
|
||||
MessageBusConnection connection = ApplicationManager.getApplication().getMessageBus().connect(parentDisposable);
|
||||
connection.subscribe(FileTypeManager.TOPIC, new FileTypeListener.Adapter() {
|
||||
@Override
|
||||
public void fileTypesChanged(@NotNull FileTypeEvent event) {
|
||||
reinitRoots();
|
||||
resetIndex();
|
||||
}
|
||||
});
|
||||
|
||||
connection.subscribe(VirtualFileManager.VFS_CHANGES, new BulkFileListener() {
|
||||
@Override
|
||||
public void before(@NotNull List<? extends VFileEvent> events) {
|
||||
@@ -60,7 +66,7 @@ abstract class LightDirectoryIndex<T> {
|
||||
for (VFileEvent event : events) {
|
||||
VirtualFile file = event.getFile();
|
||||
if (file == null || file.isDirectory()) {
|
||||
reinitRoots();
|
||||
resetIndex();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -68,15 +74,20 @@ abstract class LightDirectoryIndex<T> {
|
||||
});
|
||||
}
|
||||
|
||||
public void reinitRoots() {
|
||||
public void resetIndex() {
|
||||
myInfoCache.clear();
|
||||
collectRoots((file, info) -> cacheInfo(file, info));
|
||||
myInitializer.consume(this);
|
||||
}
|
||||
|
||||
protected abstract void collectRoots(@NotNull PairConsumer<VirtualFile, T> consumer);
|
||||
public void putInfo(@Nullable VirtualFile file, @NotNull T value) {
|
||||
if (!(file instanceof VirtualFileWithId)) return;
|
||||
cacheInfo(file, value);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public T getInfoForFile(@NotNull VirtualFile file) {
|
||||
public T getInfoForFile(@Nullable VirtualFile file) {
|
||||
if (!(file instanceof VirtualFileWithId)) return myDefValue;
|
||||
|
||||
VirtualFile dir;
|
||||
if (!file.isDirectory()) {
|
||||
T info = getCachedInfo(file);
|
||||
@@ -39,8 +39,7 @@ public enum EffectPainter implements RegionPainter<Paint> {
|
||||
}
|
||||
else if (paint != null && width > 0 && height > 0) {
|
||||
int h = height > 6 && Registry.is("ide.text.effect.wave.new.scale") ? height >> 1 : 3;
|
||||
double pos = Registry.doubleValue("ide.text.effect.line.new.pos");
|
||||
y += height < 3 ? 1 : (int)((double)height - h * pos);
|
||||
y += height - 1 - h / 2;
|
||||
g.setPaint(paint);
|
||||
g.drawLine(x, y, x + width, y);
|
||||
}
|
||||
@@ -60,25 +59,17 @@ public enum EffectPainter implements RegionPainter<Paint> {
|
||||
WavePainter.forColor(g.getColor()).paint(g, x, x + width, y + height);
|
||||
}
|
||||
else if (paint != null && width > 0 && height > 0) {
|
||||
boolean simple = height < 5;
|
||||
int h = height > 6 && Registry.is("ide.text.effect.wave.new.scale") ? height >> 1 : 3;
|
||||
if (h != height) {
|
||||
y += height - h;
|
||||
height = h;
|
||||
}
|
||||
g = (Graphics2D)g.create(x, y, width, height);
|
||||
g.clipRect(0, -1, width, height + 1); // 1px for Retina painting
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g.setPaint(paint);
|
||||
|
||||
int length = 2 * height - 2; // the spatial period of the wave
|
||||
g.clipRect(0, 0, width, height);
|
||||
int h = height > 6 && Registry.is("ide.text.effect.wave.new.scale") ? height >> 1 : 3;
|
||||
int length = 2 * h - 2; // the spatial period of the wave
|
||||
|
||||
double dx = -((x % length + length) % length); // normalize
|
||||
double upper = 0;
|
||||
double upper = height - h;
|
||||
double lower = height - 1;
|
||||
Path2D path = new Path2D.Double();
|
||||
path.moveTo(dx, lower);
|
||||
if (simple) {
|
||||
if (height < 6) {
|
||||
g.setStroke(STROKE);
|
||||
double size = (double)length / 2;
|
||||
while (true) {
|
||||
@@ -91,7 +82,7 @@ public enum EffectPainter implements RegionPainter<Paint> {
|
||||
else {
|
||||
double size = (double)length / 4;
|
||||
double prev = dx - size / 2;
|
||||
double center = lower / 2;
|
||||
double center = (upper + lower) / 2;
|
||||
while (true) {
|
||||
path.quadTo(prev += size, lower, dx += size, center);
|
||||
if (dx > width) break;
|
||||
@@ -103,6 +94,8 @@ public enum EffectPainter implements RegionPainter<Paint> {
|
||||
if (dx > width) break;
|
||||
}
|
||||
}
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
g.setPaint(paint);
|
||||
g.draw(path);
|
||||
g.dispose();
|
||||
}
|
||||
|
||||
+2
-1
@@ -112,7 +112,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
private int myInEditorPaintCounter; // EDT only
|
||||
private final long myStartTime;
|
||||
@Nullable
|
||||
private final Splash mySplash;
|
||||
private Splash mySplash;
|
||||
private boolean myDoNotSave;
|
||||
private volatile boolean myDisposeInProgress;
|
||||
|
||||
@@ -420,6 +420,7 @@ public class ApplicationImpl extends PlatformComponentManagerImpl implements App
|
||||
token.finish();
|
||||
}
|
||||
myLoaded = true;
|
||||
mySplash = null;
|
||||
|
||||
createLocatorFile();
|
||||
}
|
||||
|
||||
@@ -21,38 +21,82 @@ import com.intellij.util.ui.UIUtil;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.AWTEventListener;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static com.intellij.icons.AllIcons.Ide.Shadow.Popup.*;
|
||||
import static com.intellij.util.containers.ContainerUtil.newArrayList;
|
||||
|
||||
/**
|
||||
* @author Sergey.Malenkov
|
||||
*/
|
||||
final class WindowShadowPainter extends AbstractPainter {
|
||||
final class WindowShadowPainter extends AbstractPainter implements AWTEventListener {
|
||||
private static final ShadowPainter PAINTER = new ShadowPainter(Top, Top_right, Right, Bottom_right, Bottom, Bottom_left, Left, Top_left);
|
||||
private static final long MASK = AWTEvent.WINDOW_EVENT_MASK | AWTEvent.WINDOW_STATE_EVENT_MASK | AWTEvent.COMPONENT_EVENT_MASK;
|
||||
private List<Rectangle> myShadows;
|
||||
private Component myComponent;
|
||||
|
||||
WindowShadowPainter() {
|
||||
setNeedsRepaint(true);
|
||||
@Override
|
||||
public boolean needsRepaint() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eventDispatched(AWTEvent event) {
|
||||
Component component = myComponent;
|
||||
if (component == null) return;
|
||||
Window window = UIUtil.getWindow(component);
|
||||
if (window == null) return;
|
||||
Object source = event.getSource();
|
||||
if (source instanceof Window && SwingUtilities.isDescendingFrom((Window)source, window)) {
|
||||
List<Rectangle> shadows = myShadows;
|
||||
myShadows = getShadows(component, window);
|
||||
if (!Objects.equals(myShadows, shadows)) component.repaint();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executePaint(Component component, Graphics2D g) {
|
||||
Window window = UIUtil.getWindow(component);
|
||||
if (window != null) {
|
||||
Point point = new Point();
|
||||
SwingUtilities.convertPointToScreen(point, component);
|
||||
paintShadows(component, g, point, window.getOwnedWindows());
|
||||
setNeedsRepaint(true);
|
||||
if (myComponent != component) {
|
||||
boolean add = myComponent == null;
|
||||
myComponent = component;
|
||||
myShadows = getShadows(component, window);
|
||||
if (add) Toolkit.getDefaultToolkit().addAWTEventListener(this, MASK);
|
||||
}
|
||||
List<Rectangle> shadows = myShadows;
|
||||
if (shadows != null) {
|
||||
for (Rectangle bounds : shadows) {
|
||||
PAINTER.paintShadow(component, g, bounds.x, bounds.y, bounds.width, bounds.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (myComponent != null) {
|
||||
Toolkit.getDefaultToolkit().removeAWTEventListener(this);
|
||||
myComponent = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void paintShadows(Component component, Graphics2D g, Point point, Window... windows) {
|
||||
private static List<Rectangle> getShadows(Component component, Window window) {
|
||||
Point point = new Point();
|
||||
SwingUtilities.convertPointToScreen(point, component);
|
||||
return getShadows(null, point, window.getOwnedWindows());
|
||||
}
|
||||
|
||||
private static List<Rectangle> getShadows(List<Rectangle> list, Point point, Window... windows) {
|
||||
if (windows != null) {
|
||||
for (Window window : windows) {
|
||||
Rectangle bounds = getShadowBounds(point, window);
|
||||
if (bounds != null) PAINTER.paintShadow(component, g, bounds.x, bounds.y, bounds.width, bounds.height);
|
||||
paintShadows(component, g, point, window.getOwnedWindows());
|
||||
if (bounds != null) {
|
||||
if (list == null) list = newArrayList();
|
||||
list.add(bounds);
|
||||
}
|
||||
list = getShadows(list, point, window.getOwnedWindows());
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private static Rectangle getShadowBounds(Point point, Window window) {
|
||||
|
||||
@@ -359,6 +359,7 @@
|
||||
<fileIconProvider implementation="com.intellij.ide.scratch.ScratchFileServiceImpl$FilePresentation"/>
|
||||
<editorTabTitleProvider implementation="com.intellij.ide.scratch.ScratchFileServiceImpl$FilePresentation"/>
|
||||
<syntaxHighlighter factoryClass="com.intellij.ide.scratch.ScratchFileServiceImpl$Highlighter" order="first"/>
|
||||
<indexedRootsProvider implementation="com.intellij.ide.scratch.ScratchFileServiceImpl$IndexSetContributor"/>
|
||||
|
||||
<scratch.rootType implementation="com.intellij.ide.scratch.ScratchRootType" />
|
||||
<scratch.rootType implementation="com.intellij.execution.console.HistoryRootType"/>
|
||||
|
||||
@@ -768,8 +768,6 @@ editor.rainbow.identifiers.description=Rainbow identifiers in editor
|
||||
|
||||
ide.text.effect.line.new=false
|
||||
ide.text.effect.line.new.description=Enables new line painter for text
|
||||
ide.text.effect.line.new.pos=0.5
|
||||
ide.text.effect.line.new.pos.description=Changes a line position
|
||||
ide.text.effect.wave.new=false
|
||||
ide.text.effect.wave.new.description=Enables new wave painter for text
|
||||
ide.text.effect.wave.new.scale=false
|
||||
|
||||
+1
-1
@@ -2385,7 +2385,7 @@
|
||||
level="WARNING" implementationClass="com.siyeh.ig.style.ConstantOnRHSOfComparisonInspection"/>
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="ControlFlowStatementWithoutBraces" bundle="com.siyeh.InspectionGadgetsBundle"
|
||||
key="control.flow.statement.without.braces.display.name" groupBundle="messages.InspectionsBundle"
|
||||
groupKey="group.names.code.style.issues" enabledByDefault="false" level="WARNING"
|
||||
groupKey="group.names.code.style.issues" enabledByDefault="true" level="INFORMATION"
|
||||
implementationClass="com.siyeh.ig.style.ControlFlowStatementWithoutBracesInspection"/>
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="EqualsCalledOnEnumConstant" bundle="com.siyeh.InspectionGadgetsBundle"
|
||||
key="equals.called.on.enum.constant.display.name" groupBundle="messages.InspectionsBundle"
|
||||
|
||||
+2
-1
@@ -1004,7 +1004,7 @@ too.broad.scope.problem.descriptor=Scope of variable <code>#ref</code> is too br
|
||||
return.this.problem.descriptor=Return of <code>#ref</code> #loc
|
||||
constant.on.lhs.of.comparison.problem.descriptor=<code>#ref</code>: constant on left side of comparison #loc
|
||||
constant.on.rhs.of.comparison.problem.descriptor=<code>#ref</code>: constant on right side of comparison #loc
|
||||
control.flow.statement.without.braces.problem.descriptor=<code>#ref</code> without braces #loc
|
||||
control.flow.statement.without.braces.problem.descriptor=<code>{0}</code> without braces #loc
|
||||
missorted.modifiers.problem.descriptor=Missorted modifiers <code>#ref</code> #loc
|
||||
cstyle.array.variable.declaration.problem.descriptor=C-style array declaration of {0, choice, 1#field|2#parameter|3#local variable} <code>#ref</code> #loc
|
||||
cstyle.array.method.declaration.problem.descriptor=C-style array declaration of the return type of method <code>#ref()</code>#loc
|
||||
@@ -1335,6 +1335,7 @@ introduce.variable.quickfix=Introduce variable
|
||||
introduce.variable.may.change.semantics.quickfix=Introduce variable (may change semantics)
|
||||
flip.comparison.quickfix=Flip comparison
|
||||
control.flow.statement.without.braces.add.quickfix=Add braces
|
||||
control.flow.statement.without.braces.message=Add braces to ''{0}'' statement
|
||||
extends.object.remove.quickfix=Remove redundant 'extends Object'
|
||||
implicit.call.to.super.ignore.option=Ignore for direct subclasses of 'java.lang.Object'
|
||||
implicit.call.to.super.make.explicit.quickfix=Make call to 'super()' explicit
|
||||
|
||||
+23
-7
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.siyeh.ig;
|
||||
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.codeInspection.ProblemHighlightType;
|
||||
import com.intellij.codeInspection.ProblemsHolder;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
@@ -183,10 +185,7 @@ public abstract class BaseInspectionVisitor extends JavaElementVisitor {
|
||||
if (!location.isPhysical() || location.getTextLength() == 0 && !(location instanceof PsiFile)) {
|
||||
return;
|
||||
}
|
||||
final InspectionGadgetsFix[] fixes = createFixes(infos);
|
||||
for (InspectionGadgetsFix fix : fixes) {
|
||||
fix.setOnTheFly(onTheFly);
|
||||
}
|
||||
final LocalQuickFix[] fixes = createAndInitFixes(infos);
|
||||
final String description = inspection.buildErrorString(infos);
|
||||
holder.registerProblem(location, description, highlightType, fixes);
|
||||
}
|
||||
@@ -201,13 +200,30 @@ public abstract class BaseInspectionVisitor extends JavaElementVisitor {
|
||||
if (location.getTextLength() == 0 || length == 0) {
|
||||
return;
|
||||
}
|
||||
final LocalQuickFix[] fixes = createAndInitFixes(infos);
|
||||
final String description = inspection.buildErrorString(infos);
|
||||
final TextRange range = new TextRange(offset, offset + length);
|
||||
holder.registerProblem(location, description, highlightType, range, fixes);
|
||||
}
|
||||
|
||||
protected final void registerErrorAtRange(@NotNull PsiElement startLocation, @NotNull PsiElement endLocation, Object... infos) {
|
||||
if (startLocation.getTextLength() == 0 && startLocation == endLocation) {
|
||||
return;
|
||||
}
|
||||
final LocalQuickFix[] fixes = createAndInitFixes(infos);
|
||||
final String description = inspection.buildErrorString(infos);
|
||||
final ProblemDescriptor problemDescriptor = holder.getManager()
|
||||
.createProblemDescriptor(startLocation, endLocation, description, ProblemHighlightType.GENERIC_ERROR_OR_WARNING, onTheFly, fixes);
|
||||
holder.registerProblem(problemDescriptor);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private LocalQuickFix[] createAndInitFixes(Object[] infos) {
|
||||
final InspectionGadgetsFix[] fixes = createFixes(infos);
|
||||
for (InspectionGadgetsFix fix : fixes) {
|
||||
fix.setOnTheFly(onTheFly);
|
||||
}
|
||||
final String description = inspection.buildErrorString(infos);
|
||||
final TextRange range = new TextRange(offset, offset + length);
|
||||
holder.registerProblem(location, description, highlightType, range, fixes);
|
||||
return fixes;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
+85
-20
@@ -15,8 +15,12 @@
|
||||
*/
|
||||
package com.siyeh.ig.style;
|
||||
|
||||
import com.intellij.codeHighlighting.HighlightDisplayLevel;
|
||||
import com.intellij.codeInsight.daemon.HighlightDisplayKey;
|
||||
import com.intellij.codeInspection.InspectionProfile;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
@@ -24,12 +28,17 @@ import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.InspectionGadgetsFix;
|
||||
import com.siyeh.ig.PsiReplacementUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ControlFlowStatementWithoutBracesInspection
|
||||
extends BaseInspection {
|
||||
|
||||
private static final String DO_TEXT = "do";
|
||||
private static final String ELSE_TEXT = "else";
|
||||
private static final String FOR_TEXT = "for";
|
||||
private static final String IF_TEXT = "if";
|
||||
private static final String WHILE_TEXT = "while";
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getDisplayName() {
|
||||
@@ -41,38 +50,52 @@ public class ControlFlowStatementWithoutBracesInspection
|
||||
@NotNull
|
||||
protected String buildErrorString(Object... infos) {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"control.flow.statement.without.braces.problem.descriptor");
|
||||
"control.flow.statement.without.braces.problem.descriptor", infos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InspectionGadgetsFix buildFix(Object... infos) {
|
||||
return new ControlFlowStatementFix();
|
||||
if (infos.length == 1 && infos[0] instanceof String) {
|
||||
return new ControlFlowStatementFix((String)infos[0]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class ControlFlowStatementFix extends InspectionGadgetsFix {
|
||||
private final String myKeywordText;
|
||||
|
||||
public ControlFlowStatementFix(String keywordText) {
|
||||
myKeywordText = keywordText;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"control.flow.statement.without.braces.add.quickfix");
|
||||
"control.flow.statement.without.braces.message", myKeywordText);
|
||||
}
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
return getName();
|
||||
return InspectionGadgetsBundle.message(
|
||||
"control.flow.statement.without.braces.add.quickfix");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFix(Project project, ProblemDescriptor descriptor)
|
||||
throws IncorrectOperationException {
|
||||
final PsiElement element = descriptor.getPsiElement();
|
||||
final PsiElement element = descriptor.getStartElement();
|
||||
final PsiElement parent = element.getParent();
|
||||
if (!(parent instanceof PsiStatement)) {
|
||||
final PsiStatement statement;
|
||||
if (element instanceof PsiStatement) {
|
||||
statement = (PsiStatement)element;
|
||||
}
|
||||
else if ((parent instanceof PsiStatement)) {
|
||||
statement = (PsiStatement)parent;
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
final PsiStatement statement = (PsiStatement)parent;
|
||||
@NonNls final String elementText = element.getText();
|
||||
final PsiStatement statementWithoutBraces;
|
||||
if (statement instanceof PsiLoopStatement) {
|
||||
final PsiLoopStatement loopStatement =
|
||||
@@ -81,7 +104,10 @@ public class ControlFlowStatementWithoutBracesInspection
|
||||
}
|
||||
else if (statement instanceof PsiIfStatement) {
|
||||
final PsiIfStatement ifStatement = (PsiIfStatement)statement;
|
||||
if ("if".equals(elementText)) {
|
||||
if (element == ifStatement.getElseElement()) {
|
||||
statementWithoutBraces = ifStatement.getElseBranch();
|
||||
}
|
||||
else {
|
||||
statementWithoutBraces = ifStatement.getThenBranch();
|
||||
if (statementWithoutBraces == null) {
|
||||
return;
|
||||
@@ -93,9 +119,6 @@ public class ControlFlowStatementWithoutBracesInspection
|
||||
nextSibling.delete();
|
||||
}
|
||||
}
|
||||
else {
|
||||
statementWithoutBraces = ifStatement.getElseBranch();
|
||||
}
|
||||
}
|
||||
else {
|
||||
return;
|
||||
@@ -111,11 +134,18 @@ public class ControlFlowStatementWithoutBracesInspection
|
||||
|
||||
@Override
|
||||
public BaseInspectionVisitor buildVisitor() {
|
||||
return new ControlFlowStatementVisitor();
|
||||
final String shortName = getShortName();
|
||||
final HighlightDisplayKey key = HighlightDisplayKey.find(shortName);
|
||||
return new ControlFlowStatementVisitor(key);
|
||||
}
|
||||
|
||||
private static class ControlFlowStatementVisitor
|
||||
extends BaseInspectionVisitor {
|
||||
private HighlightDisplayKey myKey;
|
||||
|
||||
public ControlFlowStatementVisitor(HighlightDisplayKey key) {
|
||||
myKey = key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitDoWhileStatement(PsiDoWhileStatement statement) {
|
||||
@@ -124,7 +154,7 @@ public class ControlFlowStatementWithoutBracesInspection
|
||||
if (body == null || body instanceof PsiBlockStatement) {
|
||||
return;
|
||||
}
|
||||
registerStatementError(statement);
|
||||
registerKeywordOrStatementError(statement, DO_TEXT);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -134,7 +164,7 @@ public class ControlFlowStatementWithoutBracesInspection
|
||||
if (body == null || body instanceof PsiBlockStatement) {
|
||||
return;
|
||||
}
|
||||
registerStatementError(statement);
|
||||
registerKeywordOrStatementError(statement, FOR_TEXT);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -144,7 +174,7 @@ public class ControlFlowStatementWithoutBracesInspection
|
||||
if (body == null || body instanceof PsiBlockStatement) {
|
||||
return;
|
||||
}
|
||||
registerStatementError(statement);
|
||||
registerKeywordOrStatementError(statement, FOR_TEXT);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -154,8 +184,15 @@ public class ControlFlowStatementWithoutBracesInspection
|
||||
if (thenBranch == null) {
|
||||
return;
|
||||
}
|
||||
boolean highlightOnlyKeyword = isHighlightOnlyKeyword(statement);
|
||||
if (!(thenBranch instanceof PsiBlockStatement)) {
|
||||
registerStatementError(statement);
|
||||
if (highlightOnlyKeyword) {
|
||||
registerStatementError(statement, IF_TEXT);
|
||||
}
|
||||
else {
|
||||
final PsiElement startElement = statement.getFirstChild();
|
||||
registerErrorAtRange(startElement != null ? startElement : thenBranch, thenBranch, IF_TEXT);
|
||||
}
|
||||
}
|
||||
final PsiStatement elseBranch = statement.getElseBranch();
|
||||
if (elseBranch == null) {
|
||||
@@ -167,7 +204,12 @@ public class ControlFlowStatementWithoutBracesInspection
|
||||
if (elseKeyword == null) {
|
||||
return;
|
||||
}
|
||||
registerError(elseKeyword);
|
||||
if (highlightOnlyKeyword) {
|
||||
registerError(elseKeyword, ELSE_TEXT);
|
||||
}
|
||||
else {
|
||||
registerErrorAtRange(elseKeyword, elseBranch, ELSE_TEXT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +220,30 @@ public class ControlFlowStatementWithoutBracesInspection
|
||||
if (body == null || body instanceof PsiBlockStatement) {
|
||||
return;
|
||||
}
|
||||
registerStatementError(statement);
|
||||
registerKeywordOrStatementError(statement, WHILE_TEXT);
|
||||
}
|
||||
|
||||
private void registerKeywordOrStatementError(PsiStatement statement, String text) {
|
||||
boolean highlightOnlyKeyword = isHighlightOnlyKeyword(statement);
|
||||
if (highlightOnlyKeyword) {
|
||||
registerStatementError(statement, text);
|
||||
}
|
||||
else {
|
||||
registerError(statement, text);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isHighlightOnlyKeyword(PsiElement element) {
|
||||
if (!isOnTheFly()) {
|
||||
return true;
|
||||
}
|
||||
if (myKey != null) {
|
||||
final Project project = element.getProject();
|
||||
final InspectionProfile profile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile();
|
||||
HighlightDisplayLevel errorLevel = profile.getErrorLevel(myKey, element);
|
||||
return !HighlightDisplayLevel.DO_NOT_SHOW.equals(errorLevel);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
int j = 0;
|
||||
do {
|
||||
System.out.println(a[j++]);
|
||||
}
|
||||
while (j < a.length);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
int j = 0;
|
||||
do System.out.println<caret>(a[j++]);
|
||||
while (j < a.length);
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
int j = 0;
|
||||
do {
|
||||
System.out.println(a[j++]);
|
||||
}
|
||||
while (j < a.length);
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
int j = 0;
|
||||
do System.out.println(a[j++]);
|
||||
while (j < a<caret>.length);
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
int j = 0;
|
||||
do {
|
||||
System.out.println(a[j++]);
|
||||
}
|
||||
while (j < a.length);
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
int j = 0;
|
||||
do System.out.println(a[j++]);<caret>
|
||||
while (j < a.length);
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
for (String s : a) {
|
||||
System.out.println(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
for (String s : a)
|
||||
System.out.println(s)<caret>;
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
for (String s : a) {
|
||||
System.out.println(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
for (String s : <caret>a)
|
||||
System.out.println(s);
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
for (String s : a) {
|
||||
System.out.println(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
<caret>for (String s : a)
|
||||
System.out.println(s);
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
for (int i = 0; i < a.length; i++) {
|
||||
System.out.println(a[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
for<caret> (int i = 0; i < a.length; i++)
|
||||
System.out.println(a[i]);
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
if (a.length == 0) {
|
||||
System.out.println("no");
|
||||
} else
|
||||
System.out.println(a.length);
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
if (a.length == 0)
|
||||
System<caret>.out.println("no");
|
||||
else
|
||||
System.out.println(a.length);
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
if (a.length == 0)
|
||||
System.out.println("no");
|
||||
else {
|
||||
System.out.println(a.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
if (a.length == 0)
|
||||
System.out.println("no");
|
||||
else
|
||||
System<caret>.out.println(a.length);
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
if (a.length == 0)
|
||||
System.out.println("no");
|
||||
else {
|
||||
System.out.println(a.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
if (a.length == 0)
|
||||
System.out.println("no");
|
||||
<caret>else
|
||||
System.out.println(a.length);
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
if (a.length == 0) {
|
||||
System.out.println("no");
|
||||
} else
|
||||
System.out.println(a.length);
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
<caret>if (a.length == 0)
|
||||
System.out.println("no");
|
||||
else
|
||||
System.out.println(a.length);
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
if (a.length == 0)
|
||||
System.out.println("no"); <caret>
|
||||
else
|
||||
System.out.println(a.length);
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
if (a.length == 0) {
|
||||
System.out.println("no");
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
if (a.length == 0)
|
||||
System.<caret>out.println("no");
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
if (a.length == 0) {
|
||||
System.out.println("no");
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
if (a.length<caret> == 0)
|
||||
System.out.println("no");
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
if (a.length == 0) {
|
||||
System.out.println("no");
|
||||
}
|
||||
}
|
||||
}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
<caret>if (a.length == 0)
|
||||
System.out.println("no");
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
int k = 0;
|
||||
while (k < a.length) {
|
||||
System.out.println(a[k++]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
int k = 0;
|
||||
while <caret>(k < a.length)
|
||||
System.out.println(a[k++]);
|
||||
}
|
||||
}
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
int k = 0;<caret>
|
||||
while (k < a.length)
|
||||
System.out.println(a[k++]);
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
class T {
|
||||
void f(String[] a) {
|
||||
for (String s : a)
|
||||
System.out.println(s);
|
||||
|
||||
if (a.length == 0)
|
||||
System.out.println("no");
|
||||
else
|
||||
System.out.println(a.length);
|
||||
|
||||
for (int i = 0; i < a.length; i++)
|
||||
System.out.println(a[i]);
|
||||
|
||||
int j = 0;
|
||||
do System.out.println(a[j++]);
|
||||
while (j < a.length);
|
||||
|
||||
int k = 0;
|
||||
while (k < a.length)
|
||||
System.out.println(a[k++]);
|
||||
|
||||
if (a.length == 0)
|
||||
System.out.println("no");
|
||||
|
||||
if (a.length == 0) {
|
||||
} else
|
||||
System.out.println(a.length);
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<problems>
|
||||
|
||||
<problem>
|
||||
<file>ControlFlowStatements.java</file>
|
||||
<line>3</line>
|
||||
<problem_class>Control flow statement without braces</problem_class>
|
||||
<description><code>for</code> without braces #loc</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>ControlFlowStatements.java</file>
|
||||
<line>6</line>
|
||||
<problem_class>Control flow statement without braces</problem_class>
|
||||
<description><code>if</code> without braces #loc</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>ControlFlowStatements.java</file>
|
||||
<line>8</line>
|
||||
<problem_class>Control flow statement without braces</problem_class>
|
||||
<description><code>else</code> without braces #loc</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>ControlFlowStatements.java</file>
|
||||
<line>11</line>
|
||||
<problem_class>Control flow statement without braces</problem_class>
|
||||
<description><code>for</code> without braces #loc</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>ControlFlowStatements.java</file>
|
||||
<line>15</line>
|
||||
<problem_class>Control flow statement without braces</problem_class>
|
||||
<description><code>do</code> without braces #loc</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>ControlFlowStatements.java</file>
|
||||
<line>19</line>
|
||||
<problem_class>Control flow statement without braces</problem_class>
|
||||
<description><code>while</code> without braces #loc</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>ControlFlowStatements.java</file>
|
||||
<line>22</line>
|
||||
<problem_class>Control flow statement without braces</problem_class>
|
||||
<description><code>if</code> without braces #loc</description>
|
||||
</problem>
|
||||
|
||||
<problem>
|
||||
<file>ControlFlowStatements.java</file>
|
||||
<line>26</line>
|
||||
<problem_class>Control flow statement without braces</problem_class>
|
||||
<description><code>else</code> without braces #loc</description>
|
||||
</problem>
|
||||
|
||||
</problems>
|
||||
@@ -116,8 +116,9 @@ public abstract class IGQuickFixesTestCase extends JavaCodeInsightFixtureTestCas
|
||||
}
|
||||
|
||||
public IntentionAction findIntention(@NotNull final String hint) {
|
||||
final List<IntentionAction> allIntentions = myFixture.getAvailableIntentions();
|
||||
final List<IntentionAction> intentions =
|
||||
ContainerUtil.findAll(myFixture.getAvailableIntentions(),
|
||||
ContainerUtil.findAll(allIntentions,
|
||||
intentionAction -> intentionAction instanceof QuickFixWrapper &&
|
||||
intentionAction.getText().equals(hint));
|
||||
Assert.assertFalse("\"" + hint + "\" not in " + intentions, intentions.isEmpty());
|
||||
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.siyeh.ig.fixes.braces;
|
||||
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.IGQuickFixesTestCase;
|
||||
import com.siyeh.ig.style.ControlFlowStatementWithoutBracesInspection;
|
||||
|
||||
/**
|
||||
* @author Pavel.Dolgov
|
||||
*/
|
||||
public class ControlFlowStatementWithoutBracesFixTest extends IGQuickFixesTestCase {
|
||||
|
||||
public void testSimpleIfBody() { doTest("if"); }
|
||||
public void testSimpleIfExpression() { doTest("if"); }
|
||||
public void testSimpleIfKeyword() { doTest("if"); }
|
||||
|
||||
public void testFullIfBody() { doTest("if"); }
|
||||
public void testFullIfKeyword() { doTest("if"); }
|
||||
public void testFullIfElseBody() { doTest("else"); }
|
||||
public void testFullIfElseKeyword() { doTest("else"); }
|
||||
public void testFullIfMiddle() { assertQuickfixNotAvailable(getMessagePrefix()); }
|
||||
|
||||
public void testDoBody() { doTest("do"); }
|
||||
public void testDoExpression() { doTest("do"); }
|
||||
public void testDoMiddle() { doTest("do"); }
|
||||
|
||||
public void testForEachBody() { doTest("for"); }
|
||||
public void testForEachExpression() { doTest("for"); }
|
||||
public void testForEachKeyword() { doTest("for"); }
|
||||
public void testForIndex() { doTest("for"); }
|
||||
|
||||
public void testWhile() { doTest("while"); }
|
||||
public void testWhileOutside() { assertQuickfixNotAvailable(getMessagePrefix()); }
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
myRelativePath = "statement_without_braces";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BaseInspection getInspection() {
|
||||
return new ControlFlowStatementWithoutBracesInspection();
|
||||
}
|
||||
|
||||
protected void doTest(String keyword) {
|
||||
super.doTest(getMessage(keyword));
|
||||
}
|
||||
|
||||
private static String getMessage(String keyword) {
|
||||
return InspectionGadgetsBundle.message("control.flow.statement.without.braces.message", keyword);
|
||||
}
|
||||
|
||||
private static String getMessagePrefix() {
|
||||
final String message = InspectionGadgetsBundle.message("control.flow.statement.without.braces.message", "@");
|
||||
final int index = message.indexOf("@");
|
||||
if (index >= 0) return message.substring(0, index);
|
||||
return message;
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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.siyeh.ig.style;
|
||||
|
||||
import com.siyeh.ig.IGInspectionTestCase;
|
||||
|
||||
/**
|
||||
* @author Pavel.Dolgov
|
||||
*/
|
||||
public class ControlFlowStatementWithoutBracesInspectionTest extends IGInspectionTestCase {
|
||||
public void test() {
|
||||
doTest("com/siyeh/igtest/style/statements_without_braces", new ControlFlowStatementWithoutBracesInspection());
|
||||
}
|
||||
}
|
||||
@@ -351,11 +351,6 @@
|
||||
<bundleName>com.siyeh.IntentionPowerPackBundle</bundleName>
|
||||
<categoryKey>intention.category.control.flow</categoryKey>
|
||||
</intentionAction>
|
||||
<intentionAction>
|
||||
<className>com.siyeh.ipp.braces.AddBracesIntention</className>
|
||||
<bundleName>com.siyeh.IntentionPowerPackBundle</bundleName>
|
||||
<categoryKey>intention.category.control.flow</categoryKey>
|
||||
</intentionAction>
|
||||
<intentionAction>
|
||||
<className>com.siyeh.ipp.braces.RemoveBracesIntention</className>
|
||||
<bundleName>com.siyeh.IntentionPowerPackBundle</bundleName>
|
||||
|
||||
@@ -90,7 +90,6 @@ flip.comparison.intention.family.name=Flip Comparison
|
||||
flip.conjunction.intention.family.name=Flip Conjunction Operands
|
||||
negate.comparison.intention.family.name=Negate Comparison
|
||||
remove.braces.intention.family.name=Remove Braces
|
||||
add.braces.intention.family.name=Add Braces
|
||||
flip.commutative.method.call.intention.family.name=Flip Commutative Method Call
|
||||
constant.subexpression.intention.family.name=Compute Constant Value for Subexpression
|
||||
extract.increment.intention.family.name=Extract Increment
|
||||
@@ -172,7 +171,6 @@ flip.smth.intention.name1=Flip ''{0}'' (changes semantics)
|
||||
flip.comparison.intention.name=Flip ''{0}'' to ''{1}''
|
||||
negate.comparison.intention.name=Negate ''{0}''
|
||||
negate.comparison.intention.name1=Negate ''{0}'' to ''{1}''
|
||||
add.braces.intention.name=Add braces to ''{0}'' statement
|
||||
remove.braces.intention.name=Remove braces from ''{0}'' statement
|
||||
flip.commutative.method.call.intention.name=Flip ''.{0}()''
|
||||
flip.commutative.method.call.intention.name1=Flip ''.{0}()'' (may change semantics)
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright 2003-2006 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* 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.siyeh.ipp.braces;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.siyeh.ig.PsiReplacementUtil;
|
||||
import com.siyeh.ipp.base.PsiElementPredicate;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class AddBracesIntention extends BaseBracesIntention {
|
||||
|
||||
@NotNull
|
||||
protected PsiElementPredicate getElementPredicate() {
|
||||
return new PsiElementPredicate() {
|
||||
@Override
|
||||
public boolean satisfiedBy(PsiElement element) {
|
||||
final PsiStatement statement = getSurroundingStatement(element);
|
||||
return statement != null && !(statement instanceof PsiBlockStatement);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getMessageKey() {
|
||||
return "add.braces.intention.name";
|
||||
}
|
||||
|
||||
protected void processIntention(@NotNull PsiElement element) throws IncorrectOperationException {
|
||||
final PsiStatement statement = getSurroundingStatement(element);
|
||||
if (statement == null) {
|
||||
return;
|
||||
}
|
||||
final String newStatement = "{\n" + statement.getText() + "\n}";
|
||||
PsiReplacementUtil.replaceStatement(statement, newStatement);
|
||||
}
|
||||
}
|
||||
-8
@@ -1,8 +0,0 @@
|
||||
public class X {
|
||||
int f(boolean b) {
|
||||
if (b) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
public class X {
|
||||
int f(boolean b) {
|
||||
if (b) <spot>return 1</spot>;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
-6
@@ -1,6 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
This intention adds braces to control flow statements without
|
||||
braces.
|
||||
</body>
|
||||
</html>
|
||||
@@ -18,7 +18,6 @@ package org.jetbrains.idea.devkit;
|
||||
import com.intellij.execution.RunManager;
|
||||
import com.intellij.execution.RunnerAndConfigurationSettings;
|
||||
import com.intellij.execution.configurations.ConfigurationType;
|
||||
import com.intellij.ide.IdeBundle;
|
||||
import com.intellij.ide.projectWizard.NewProjectWizardTestCase;
|
||||
import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -46,14 +45,4 @@ public class PluginProjectWizardTest extends NewProjectWizardTestCase {
|
||||
VirtualFile[] files = FileEditorManager.getInstance(project).getOpenFiles();
|
||||
assertEquals(1, files.length);
|
||||
}
|
||||
|
||||
public void testProjectWithoutSdk() throws Exception {
|
||||
try {
|
||||
createProjectFromTemplate(PluginModuleType.getInstance().getName(), null, null);
|
||||
fail("Exception should be thrown");
|
||||
}
|
||||
catch (Exception e) {
|
||||
assertEquals(IdeBundle.message("prompt.confirm.project.no.jdk"), e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.apache.http.message.BasicHeader;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.github.api.GithubConnection.PagedRequest;
|
||||
import org.jetbrains.plugins.github.exceptions.GithubAuthenticationException;
|
||||
import org.jetbrains.plugins.github.exceptions.GithubConfusingException;
|
||||
import org.jetbrains.plugins.github.exceptions.GithubJsonException;
|
||||
import org.jetbrains.plugins.github.exceptions.GithubStatusCodeException;
|
||||
@@ -289,12 +290,12 @@ public class GithubApiUtil {
|
||||
try {
|
||||
repos.addAll(getMembershipRepos(connection));
|
||||
}
|
||||
catch (GithubStatusCodeException ignore) {
|
||||
catch (GithubAuthenticationException | GithubStatusCodeException ignore) {
|
||||
}
|
||||
try {
|
||||
repos.addAll(getWatchedRepos(connection));
|
||||
}
|
||||
catch (GithubStatusCodeException ignore) {
|
||||
catch (GithubAuthenticationException | GithubStatusCodeException ignore) {
|
||||
}
|
||||
|
||||
return repos;
|
||||
|
||||
@@ -130,7 +130,7 @@ abstract class BaseRepositoryManager(protected val dir: Path) : RepositoryManage
|
||||
*/
|
||||
protected abstract fun addToIndex(file: Path, path: String, content: ByteArray, size: Int)
|
||||
|
||||
override fun delete(path: String) {
|
||||
override fun delete(path: String): Boolean {
|
||||
LOG.debug { "Remove $path"}
|
||||
|
||||
lock.write {
|
||||
@@ -138,8 +138,11 @@ abstract class BaseRepositoryManager(protected val dir: Path) : RepositoryManage
|
||||
// delete could be called for non-existent file
|
||||
if (file.exists()) {
|
||||
delete(file, path)
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun delete(file: Path, path: String) {
|
||||
|
||||
@@ -242,23 +242,26 @@ class IcsApplicationLoadListener : ApplicationLoadListener {
|
||||
|
||||
val repositoryManager = icsManager.repositoryManager
|
||||
if (repositoryManager.isRepositoryExists() && repositoryManager is GitRepositoryManager) {
|
||||
if (repositoryManager.renameDirectory(linkedMapOf(
|
||||
Pair("\$ROOT_CONFIG$", null),
|
||||
Pair("_mac/\$ROOT_CONFIG$", "_mac"),
|
||||
Pair("_windows/\$ROOT_CONFIG$", "_windows"),
|
||||
Pair("_linux/\$ROOT_CONFIG$", "_linux"),
|
||||
Pair("_freebsd/\$ROOT_CONFIG$", "_freebsd"),
|
||||
Pair("_unix/\$ROOT_CONFIG$", "_unix"),
|
||||
Pair("_unknown/\$ROOT_CONFIG$", "_unknown"),
|
||||
val migrateSchemes = repositoryManager.renameDirectory(linkedMapOf(
|
||||
Pair("\$ROOT_CONFIG$", null),
|
||||
Pair("_mac/\$ROOT_CONFIG$", "_mac"),
|
||||
Pair("_windows/\$ROOT_CONFIG$", "_windows"),
|
||||
Pair("_linux/\$ROOT_CONFIG$", "_linux"),
|
||||
Pair("_freebsd/\$ROOT_CONFIG$", "_freebsd"),
|
||||
Pair("_unix/\$ROOT_CONFIG$", "_unix"),
|
||||
Pair("_unknown/\$ROOT_CONFIG$", "_unknown"),
|
||||
|
||||
Pair("\$APP_CONFIG$", null),
|
||||
Pair("_mac/\$APP_CONFIG$", "_mac"),
|
||||
Pair("_windows/\$APP_CONFIG$", "_windows"),
|
||||
Pair("_linux/\$APP_CONFIG$", "_linux"),
|
||||
Pair("_freebsd/\$APP_CONFIG$", "_freebsd"),
|
||||
Pair("_unix/\$APP_CONFIG$", "_unix"),
|
||||
Pair("_unknown/\$APP_CONFIG$", "_unknown")
|
||||
))) {
|
||||
Pair("\$APP_CONFIG$", null),
|
||||
Pair("_mac/\$APP_CONFIG$", "_mac"),
|
||||
Pair("_windows/\$APP_CONFIG$", "_windows"),
|
||||
Pair("_linux/\$APP_CONFIG$", "_linux"),
|
||||
Pair("_freebsd/\$APP_CONFIG$", "_freebsd"),
|
||||
Pair("_unix/\$APP_CONFIG$", "_unix"),
|
||||
Pair("_unknown/\$APP_CONFIG$", "_unknown")
|
||||
))
|
||||
|
||||
val removeOtherXml = repositoryManager.delete("other.xml")
|
||||
if (migrateSchemes || removeOtherXml) {
|
||||
// schedule push to avoid merge conflicts
|
||||
application.invokeLater({ icsManager.autoSyncManager.autoSync(force = true) })
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ interface RepositoryManager {
|
||||
*/
|
||||
fun write(path: String, content: ByteArray, size: Int): Boolean
|
||||
|
||||
fun delete(path: String)
|
||||
fun delete(path: String): Boolean
|
||||
|
||||
fun processChildren(path: String, filter: (name: String) -> Boolean, processor: (name: String, inputStream: InputStream) -> Boolean)
|
||||
|
||||
|
||||
@@ -113,6 +113,24 @@ public class PyPsiUtils {
|
||||
return PsiTreeUtil.skipSiblingsForward(element, PsiWhiteSpace.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds first non-whitespace sibling after given PSI element but stops at first whitespace containing line feed.
|
||||
*/
|
||||
@Nullable
|
||||
public static PsiElement getNextNonWhitespaceSiblingOnSameLine(@NotNull PsiElement element) {
|
||||
PsiElement cur = element.getNextSibling();
|
||||
while (cur != null) {
|
||||
if (!(cur instanceof PsiWhiteSpace)) {
|
||||
return cur;
|
||||
}
|
||||
else if (cur.textContains('\n')) {
|
||||
break;
|
||||
}
|
||||
cur = cur.getNextSibling();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds first non-whitespace sibling after given AST node.
|
||||
*/
|
||||
|
||||
@@ -62,7 +62,7 @@ public class PyFileElementType extends IStubFileElementType<PyFileStub> {
|
||||
@Override
|
||||
public int getStubVersion() {
|
||||
// Don't forget to update versions of indexes that use the updated stub-based elements
|
||||
return 56;
|
||||
return 57;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -890,6 +890,16 @@ public class PyUtil {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the line comment that immediately precedes statement list of the given compound statement. Python parser ensures
|
||||
* that it follows the statement header, i.e. it's directly after the colon, not on its own line.
|
||||
*/
|
||||
@Nullable
|
||||
public static PsiComment getCommentOnHeaderLine(@NotNull PyStatementListContainer container) {
|
||||
final PyStatementList statementList = container.getStatementList();
|
||||
return as(PyPsiUtils.getPrevNonWhitespaceSibling(statementList), PsiComment.class);
|
||||
}
|
||||
|
||||
public static class KnownDecoratorProviderHolder {
|
||||
public static PyKnownDecoratorProvider[] KNOWN_DECORATOR_PROVIDERS = Extensions.getExtensions(PyKnownDecoratorProvider.EP_NAME);
|
||||
|
||||
|
||||
@@ -579,12 +579,12 @@ public class PyFunctionImpl extends PyBaseElementImpl<PyFunctionStub> implements
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiComment getTypeComment() {
|
||||
final PyStatementList statements = getStatementList();
|
||||
final PsiComment inlineComment = as(PyPsiUtils.getPrevNonWhitespaceSibling(statements), PsiComment.class);
|
||||
final PsiComment inlineComment = PyUtil.getCommentOnHeaderLine(this);
|
||||
if (inlineComment != null && PyTypingTypeProvider.getTypeCommentValue(inlineComment.getText()) != null) {
|
||||
return inlineComment;
|
||||
}
|
||||
|
||||
|
||||
final PyStatementList statements = getStatementList();
|
||||
if (statements.getStatements().length != 0) {
|
||||
final PsiComment comment = as(statements.getFirstChild(), PsiComment.class);
|
||||
if (comment != null && PyTypingTypeProvider.getTypeCommentValue(comment.getText()) != null) {
|
||||
|
||||
@@ -62,6 +62,8 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static com.jetbrains.python.psi.PyUtil.as;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
*/
|
||||
@@ -682,34 +684,21 @@ public class PyTargetExpressionImpl extends PyBaseElementImpl<PyTargetExpression
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiComment getTypeComment() {
|
||||
final PsiElement commentContainer = PsiTreeUtil.getParentOfType(this,
|
||||
PyAssignmentStatement.class,
|
||||
PyWithStatement.class,
|
||||
PyForPart.class);
|
||||
if (commentContainer != null) {
|
||||
final PsiComment comment = getSameLineTrailingCommentChild(commentContainer);
|
||||
if (comment != null && PyTypingTypeProvider.getTypeCommentValue(comment.getText()) != null) {
|
||||
return comment;
|
||||
PsiComment comment = null;
|
||||
final PyAssignmentStatement assignment = PsiTreeUtil.getParentOfType(this, PyAssignmentStatement.class);
|
||||
if (assignment != null) {
|
||||
final PyExpression assignedValue = assignment.getAssignedValue();
|
||||
if (assignedValue != null) {
|
||||
comment = as(PyPsiUtils.getNextNonWhitespaceSiblingOnSameLine(assignedValue), PsiComment.class);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiComment getSameLineTrailingCommentChild(@NotNull PsiElement element) {
|
||||
PsiElement child = element.getFirstChild();
|
||||
while (true) {
|
||||
if (child == null) {
|
||||
return null;
|
||||
else {
|
||||
final PyStatementListContainer forOrWith = PsiTreeUtil.getParentOfType(this, PyForPart.class, PyWithStatement.class);
|
||||
if (forOrWith != null) {
|
||||
comment = PyUtil.getCommentOnHeaderLine(forOrWith);
|
||||
}
|
||||
if (child instanceof PsiComment) {
|
||||
return (PsiComment)child;
|
||||
}
|
||||
if (child.getText().contains("\n")) {
|
||||
return null;
|
||||
}
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
return comment != null && PyTypingTypeProvider.getTypeCommentValue(comment.getText()) != null ? comment : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -36,7 +36,6 @@ import com.jetbrains.python.psi.impl.PythonLanguageLevelPusher;
|
||||
import com.jetbrains.python.psi.stubs.PyClassNameIndex;
|
||||
import com.jetbrains.python.psi.stubs.PyNamedTupleStub;
|
||||
import com.jetbrains.python.psi.stubs.PyVariableNameIndex;
|
||||
import com.jetbrains.python.psi.types.PyClassType;
|
||||
import com.jetbrains.python.psi.types.PyType;
|
||||
import com.jetbrains.python.psi.types.TypeEvalContext;
|
||||
import com.jetbrains.python.toolbox.Maybe;
|
||||
@@ -439,39 +438,6 @@ public class PyStubsTest extends PyTestCase {
|
||||
assertNotParsed(file);
|
||||
}
|
||||
|
||||
// PY-18741
|
||||
public void testParameterTypeComment() {
|
||||
final PyFile file = getTestFile();
|
||||
final PyFunction func = file.findTopLevelFunction("func");
|
||||
assertNotNull(func);
|
||||
final PyParameter[] parameters = func.getParameterList().getParameters();
|
||||
assertSize(2, parameters);
|
||||
final PyNamedParameter param = assertInstanceOf(parameters[0], PyNamedParameter.class);
|
||||
final String annotation = param.getTypeCommentAnnotation();
|
||||
assertEquals("int", annotation);
|
||||
assertNotParsed(file);
|
||||
|
||||
final TypeEvalContext context = TypeEvalContext.codeAnalysis(myFixture.getProject(), file);
|
||||
final PyType paramType = context.getType(param);
|
||||
assertInstanceOf(paramType, PyClassType.class);
|
||||
assertNotParsed(file);
|
||||
}
|
||||
|
||||
public void testTargetExpressionTypeComment() {
|
||||
final PyFile file = getTestFile();
|
||||
final PyTargetExpression target = file.findTopLevelAttribute("x");
|
||||
assertNotNull(target);
|
||||
|
||||
final String annotation = target.getTypeCommentAnnotation();
|
||||
assertEquals("int", annotation);
|
||||
assertNotParsed(file);
|
||||
|
||||
final TypeEvalContext context = TypeEvalContext.codeAnalysis(myFixture.getProject(), file);
|
||||
final PyType paramType = context.getType(target);
|
||||
assertInstanceOf(paramType, PyClassType.class);
|
||||
assertNotParsed(file);
|
||||
}
|
||||
|
||||
public void testFullyQualifiedNamedTuple() {
|
||||
doTestNamedTuple(
|
||||
QualifiedName.fromDottedString("collections.namedtuple")
|
||||
|
||||
@@ -303,6 +303,17 @@ public class PyTypingTest extends PyTestCase {
|
||||
" expr = c1, c2\n");
|
||||
}
|
||||
|
||||
// PY-19220
|
||||
public void testMultiLineAssignmentComment() {
|
||||
doTest("List[str]",
|
||||
"from typing import List\n" +
|
||||
"\n" +
|
||||
"expr = [\n" +
|
||||
" a,\n" +
|
||||
" b,\n" +
|
||||
"] # type: List[str]");
|
||||
}
|
||||
|
||||
public void testForLoopComment() {
|
||||
doTest("int",
|
||||
"def foo(xs):\n" +
|
||||
|
||||
Reference in New Issue
Block a user