diff: support code navigation and advanced highlighting for non-local files

* disable inspections and intentions for non-local files
-- Intentions should not be available for read-only content
-- Inspections generate lots of false-positive warnings (ex: unused statement).
   Disable them until we can run only known-to-be-correct ones.
This commit is contained in:
Aleksey Pivovarov
2016-09-27 15:23:54 +03:00
parent 31dd7e7741
commit 77fc58d05f
12 changed files with 239 additions and 6 deletions
@@ -16,7 +16,7 @@
package com.intellij.codeInsight.daemon;
import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.ide.scratch.ScratchFileType;
import com.intellij.openapi.fileTypes.PeripheralFileType;
import com.intellij.openapi.roots.JavaProjectRootsUtil;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
@@ -28,7 +28,9 @@ import org.jetbrains.annotations.NotNull;
public class JavaProblemHighlightFilter extends ProblemHighlightFilter {
@Override
public boolean shouldHighlight(@NotNull PsiFile psiFile) {
return psiFile.getFileType() != JavaFileType.INSTANCE || !JavaProjectRootsUtil.isOutsideJavaSourceRoot(psiFile) || (psiFile.getViewProvider().getFileType() == ScratchFileType.INSTANCE);
return psiFile.getFileType() != JavaFileType.INSTANCE ||
!JavaProjectRootsUtil.isOutsideJavaSourceRoot(psiFile) ||
psiFile.getViewProvider().getFileType() instanceof PeripheralFileType;
}
@Override
@@ -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.intellij.openapi.fileTypes;
/**
* Marker interface for files that should be highlighted in a project context, despite of them not being part of it.
* Example: content from VCS, scratch files
*
* This file cannot be referenced from the rest of a project and might depend on no longer existent files.
* But we still can use project context to provide highlighting and code navigation in assumption, that local references are valid
* and non-local references still point at the right location.
*/
public interface PeripheralFileType extends FileType {
}
+1
View File
@@ -13,5 +13,6 @@
<orderEntry type="module" module-name="platform-impl" />
<orderEntry type="module" module-name="vcs-api-core" />
<orderEntry type="module" module-name="vcs-api" />
<orderEntry type="module" module-name="lang-api" />
</component>
</module>
@@ -0,0 +1,146 @@
/*
* 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.intellij.diff.contents;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.daemon.impl.HighlightInfoFilter;
import com.intellij.codeInsight.daemon.impl.IntentionActionFilter;
import com.intellij.codeInsight.daemon.impl.analysis.DefaultHighlightingSettingProvider;
import com.intellij.codeInsight.daemon.impl.analysis.FileHighlightingSetting;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.icons.AllIcons;
import com.intellij.lang.Language;
import com.intellij.lang.annotation.HighlightSeverity;
import com.intellij.openapi.fileTypes.*;
import com.intellij.openapi.fileTypes.ex.FileTypeIdentifiableByVirtualFile;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.LanguageSubstitutor;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
public class DiffPsiFileType extends LanguageFileType implements FileTypeIdentifiableByVirtualFile, PeripheralFileType {
public static final Key<FileType> ORIGINAL_FILE_TYPE_KEY = Key.create("Diff.DiffPsiFileType.OriginalFileTypeKey");
public static final LanguageFileType INSTANCE = new DiffPsiFileType();
DiffPsiFileType() {
super(PlainTextLanguage.INSTANCE);
}
@Override
public boolean isMyFileType(@NotNull VirtualFile file) {
return isDiffFile(file);
}
@NotNull
@Override
public String getName() {
return "Diff";
}
@NotNull
@Override
public String getDescription() {
return "Diff";
}
@NotNull
@Override
public String getDefaultExtension() {
return "";
}
@Nullable
@Override
public Icon getIcon() {
return AllIcons.Diff.Diff;
}
@Override
public boolean isReadOnly() {
return true;
}
@Nullable
@Override
public String getCharset(@NotNull VirtualFile file, @NotNull byte[] content) {
return null;
}
public static class TypeFactory extends FileTypeFactory {
@Override
public void createFileTypes(@NotNull FileTypeConsumer consumer) {
consumer.consume(INSTANCE);
}
}
public static class Substitutor extends LanguageSubstitutor {
@Nullable
@Override
public Language getLanguage(@NotNull VirtualFile file, @NotNull Project project) {
FileType originalType = getOriginalFileType(file);
if (originalType instanceof LanguageFileType) {
return ((LanguageFileType)originalType).getLanguage();
}
return null;
}
}
public static class HighlightFilter implements HighlightInfoFilter {
@Override
public boolean accept(@NotNull HighlightInfo info, @Nullable PsiFile file) {
if (!isDiffFile(file)) return true;
if (info.getSeverity() == HighlightSeverity.ERROR) return false;
return true;
}
}
public static class IntentionFilter implements IntentionActionFilter {
@Override
public boolean accept(@NotNull IntentionAction intentionAction, @Nullable PsiFile file) {
return !isDiffFile(file);
}
}
public static class HighlightingSettingProvider extends DefaultHighlightingSettingProvider {
@Nullable
@Override
public FileHighlightingSetting getDefaultSetting(@NotNull Project project, @NotNull VirtualFile file) {
if (!isDiffFile(file)) return null;
return FileHighlightingSetting.SKIP_INSPECTION;
}
}
private static boolean isDiffFile(@Nullable PsiFile file) {
return file != null && isDiffFile(file.getVirtualFile());
}
private static boolean isDiffFile(@Nullable VirtualFile file) {
return file != null && getOriginalFileType(file) != null;
}
@Nullable
private static FileType getOriginalFileType(@NotNull VirtualFile file) {
FileType fileType = file.getUserData(ORIGINAL_FILE_TYPE_KEY);
return fileType instanceof DiffPsiFileType ? null : fileType;
}
}
@@ -4,6 +4,7 @@ import com.intellij.diff.tools.util.DiffNotifications;
import com.intellij.diff.util.DiffUserDataKeysEx;
import com.intellij.diff.util.DiffUtil;
import com.intellij.diff.util.LineCol;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.EditorFactory;
import com.intellij.openapi.fileEditor.FileDocumentManager;
@@ -12,11 +13,14 @@ import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypes;
import com.intellij.openapi.fileTypes.PlainTextFileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.Navigatable;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.testFramework.LightVirtualFile;
import com.intellij.ui.LightColors;
import com.intellij.util.LineSeparator;
import com.intellij.util.diff.Diff;
@@ -107,7 +111,27 @@ public class FileAwareDocumentContent extends DocumentContentImpl {
@NotNull
private Builder create(@NotNull String content) {
mySeparator = StringUtil.detectSeparators(content);
myDocument = EditorFactory.getInstance().createDocument(StringUtil.convertLineSeparators(content));
String correctedContent = StringUtil.convertLineSeparators(content);
if (myProject != null && Registry.is("diff.enable.psi.highlighting")) {
ApplicationManager.getApplication().runReadAction(() -> {
LightVirtualFile file = new LightVirtualFile(myFileName, DiffPsiFileType.INSTANCE, correctedContent);
file.setWritable(false);
file.putUserData(DiffPsiFileType.ORIGINAL_FILE_TYPE_KEY, myFileType);
myDocument = FileDocumentManager.getInstance().getDocument(file);
if (myDocument == null) {
myDocument = EditorFactory.getInstance().createDocument(correctedContent);
}
PsiDocumentManager.getInstance(myProject).getPsiFile(myDocument);
});
}
else {
myDocument = EditorFactory.getInstance().createDocument(correctedContent);
}
myDocument.setReadOnly(true);
return this;
}
@@ -36,6 +36,7 @@ import com.intellij.diff.util.LineCol;
import com.intellij.diff.util.Side;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
@@ -43,6 +44,9 @@ import com.intellij.openapi.editor.event.DocumentEvent;
import com.intellij.openapi.editor.event.VisibleAreaEvent;
import com.intellij.openapi.editor.event.VisibleAreaListener;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.pom.Navigatable;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.CalledInAwt;
@@ -350,8 +354,23 @@ public abstract class TwosideTextDiffViewer extends TwosideDiffViewer<TextEditor
@Nullable
@Override
public Object getData(@NonNls String dataId) {
EditorEx editor = getCurrentEditor();
if (myProject != null && !myProject.isDisposed() && Registry.is("diff.enable.psi.highlighting")) {
final Object o = FileEditorManager.getInstance(myProject).getData(dataId, editor, editor.getCaretModel().getCurrentCaret());
if (o != null) return o;
}
if (DiffDataKeys.CURRENT_EDITOR.is(dataId)) {
return getCurrentEditor();
return editor;
}
else if (CommonDataKeys.EDITOR.is(dataId)) {
return editor;
}
else if (CommonDataKeys.VIRTUAL_FILE.is(dataId)) {
return editor.getVirtualFile();
}
else if (OpenFileDescriptor.NAVIGATE_IN_EDITOR.is(dataId)) {
return editor;
}
return super.getData(dataId);
}
@@ -224,7 +224,11 @@ public class DiffUtil {
public static void configureEditor(@NotNull EditorEx editor, @NotNull DocumentContent content, @Nullable Project project) {
setEditorHighlighter(project, editor, content);
setEditorCodeStyle(project, editor, content.getContentType());
editor.reinitSettings();
VirtualFile virtualFile = FileDocumentManager.getInstance().getFile(content.getDocument());
if (virtualFile != null && Registry.is("diff.enable.psi.highlighting")) {
editor.setFile(virtualFile);
}
}
public static boolean isMirrored(@NotNull Editor editor) {
@@ -16,6 +16,7 @@
package com.intellij.ide.scratch;
import com.intellij.openapi.fileTypes.LanguageFileType;
import com.intellij.openapi.fileTypes.PeripheralFileType;
import com.intellij.openapi.fileTypes.PlainTextFileType;
import com.intellij.openapi.fileTypes.PlainTextLanguage;
import com.intellij.openapi.fileTypes.ex.FileTypeIdentifiableByVirtualFile;
@@ -28,7 +29,7 @@ import javax.swing.*;
/**
* @author gregsh
*/
public class ScratchFileType extends LanguageFileType implements FileTypeIdentifiableByVirtualFile {
public class ScratchFileType extends LanguageFileType implements FileTypeIdentifiableByVirtualFile, PeripheralFileType {
public static final LanguageFileType INSTANCE = new ScratchFileType();
@@ -107,6 +107,13 @@
<colorAndFontPanelFactory implementation="com.intellij.openapi.diff.impl.settings.DiffColorsPageFactory"/>
<colorAndFontDescriptorProvider implementation="com.intellij.openapi.diff.impl.settings.DiffColorsPageFactory"/>
<fileTypeFactory implementation="com.intellij.diff.contents.DiffPsiFileType$TypeFactory"/>
<lang.substitutor language="TEXT" implementationClass="com.intellij.diff.contents.DiffPsiFileType$Substitutor" order="first"/>
<daemon.highlightInfoFilter implementation="com.intellij.diff.contents.DiffPsiFileType$HighlightFilter"/>
<daemon.intentionActionFilter implementation="com.intellij.diff.contents.DiffPsiFileType$IntentionFilter"/>
<defaultHighlightingSettingProvider id="GeneratedSourcesHighlightingSettingProvider"
implementation="com.intellij.diff.contents.DiffPsiFileType$HighlightingSettingProvider"/>
<applicationService serviceInterface="com.intellij.ui.SystemNotifications"
serviceImplementation="com.intellij.ui.SystemNotificationsImpl"/>
<applicationService serviceInterface="com.intellij.openapi.keymap.KeymapGroupFactory"
@@ -491,6 +491,8 @@ diff.divider.repainting.disable.blitting=true
diff.divider.repainting.disable.blitting.description=Fix painting glitch on scrolling in diff - disable BLIT_SCROLL_MODE to force repainting with RepaintManager
diff.merge.resolve.conflict.action.visible=false
diff.merge.resolve.conflict.action.visible.description=Allows to resolve some conflict in merge in one click (with a high probability of wrong result)
diff.enable.psi.highlighting=true
diff.enable.psi.highlighting.description=Enable advanced highlighting and code navigation in VCS content in diff viewers.
search.everywhere.toolwindows=true
search.everywhere.files=true