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:
@@ -53,6 +53,8 @@ import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.packaging.artifacts.Artifact;
|
||||
import com.intellij.packaging.impl.artifacts.ArtifactBySourceFileFinder;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.messages.MessageBusConnection;
|
||||
import org.apache.oro.text.regex.*;
|
||||
@@ -978,7 +980,15 @@ public class CompilerConfigurationImpl extends CompilerConfiguration implements
|
||||
}
|
||||
return extensionsString.toString();
|
||||
}
|
||||
|
||||
|
||||
public boolean isCompilableResourceFile(final Project project, final VirtualFile file) {
|
||||
if (!isResourceFile(file)) {
|
||||
return false;
|
||||
}
|
||||
final Collection<? extends Artifact> artifacts = ArtifactBySourceFileFinder.getInstance(project).findArtifacts(file);
|
||||
return artifacts.isEmpty();
|
||||
}
|
||||
|
||||
private static class CompiledPattern {
|
||||
@NotNull final Pattern fileName;
|
||||
@Nullable final Pattern dir;
|
||||
|
||||
@@ -26,14 +26,11 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.packaging.artifacts.Artifact;
|
||||
import com.intellij.packaging.impl.artifacts.ArtifactBySourceFileFinder;
|
||||
import com.intellij.psi.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class CompileAction extends CompileActionBase {
|
||||
@@ -108,7 +105,8 @@ public class CompileAction extends CompileActionBase {
|
||||
else if (files.length == 1) {
|
||||
final VirtualFile file = files[0];
|
||||
FileType fileType = file.getFileType();
|
||||
if (CompilerManager.getInstance(project).isCompilableFileType(fileType) || isCompilableResourceFile(project, compilerConfiguration, file)) {
|
||||
if (CompilerManager.getInstance(project).isCompilableFileType(fileType) || compilerConfiguration
|
||||
.isCompilableResourceFile(project, file)) {
|
||||
elementDescription = "'" + file.getName() + "'";
|
||||
}
|
||||
else {
|
||||
@@ -135,7 +133,7 @@ public class CompileAction extends CompileActionBase {
|
||||
}
|
||||
|
||||
private static String createPresentationText(String elementDescription) {
|
||||
StringBuffer buffer = new StringBuffer(40);
|
||||
StringBuilder buffer = new StringBuilder(40);
|
||||
buffer.append(ActionsBundle.actionText(IdeActions.ACTION_COMPILE)).append(" ");
|
||||
int length = elementDescription.length();
|
||||
if (length > 23) {
|
||||
@@ -175,20 +173,12 @@ public class CompileAction extends CompileActionBase {
|
||||
}
|
||||
else {
|
||||
FileType fileType = file.getFileType();
|
||||
if (!(compilerManager.isCompilableFileType(fileType) || isCompilableResourceFile(project, compilerConfiguration, file))) {
|
||||
if (!(compilerManager.isCompilableFileType(fileType) || compilerConfiguration.isCompilableResourceFile(project, file))) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
filesToCompile.add(file);
|
||||
}
|
||||
return VfsUtil.toVirtualFileArray(filesToCompile);
|
||||
}
|
||||
|
||||
private static boolean isCompilableResourceFile(final Project project, final CompilerConfiguration compilerConfiguration, final VirtualFile file) {
|
||||
if (!compilerConfiguration.isResourceFile(file)) {
|
||||
return false;
|
||||
}
|
||||
final Collection<? extends Artifact> artifacts = ArtifactBySourceFileFinder.getInstance(project).findArtifacts(file);
|
||||
return artifacts.isEmpty();
|
||||
return VfsUtilCore.toVirtualFileArray(filesToCompile);
|
||||
}
|
||||
}
|
||||
@@ -198,14 +198,15 @@ public class CompilerTask extends Task.Backgroundable {
|
||||
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
if (myProject.isDisposed()) {
|
||||
final Project project = myProject;
|
||||
if (project == null || project.isDisposed()) {
|
||||
return;
|
||||
}
|
||||
synchronized (myMessageViewLock) {
|
||||
// clear messages from the previous compilation
|
||||
if (myErrorTreeView == null) {
|
||||
// if message view != null, the contents has already been cleared
|
||||
removeAllContents(myProject, null);
|
||||
removeAllContents(project, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -454,7 +455,12 @@ public class CompilerTask extends Task.Backgroundable {
|
||||
if (content == notRemove) {
|
||||
continue;
|
||||
}
|
||||
if (CONTENT_ID_KEY.get(content) == myContentId || SESSION_ID_KEY.get(content) != mySessionId) { // the content was added by previous compilation
|
||||
boolean toRemove = CONTENT_ID_KEY.get(content) == myContentId;
|
||||
if (!toRemove) {
|
||||
final Object contentSessionId = SESSION_ID_KEY.get(content);
|
||||
toRemove = contentSessionId != null && contentSessionId != mySessionId; // the content was added by previous compilation
|
||||
}
|
||||
if (toRemove) {
|
||||
messageView.getContentManager().removeContent(content, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,8 @@ public abstract class CompilerConfiguration {
|
||||
|
||||
public abstract boolean isResourceFile(String path);
|
||||
|
||||
public abstract boolean isCompilableResourceFile(Project project, VirtualFile file);
|
||||
|
||||
public abstract void addResourceFilePattern(String namePattern) throws MalformedPatternException;
|
||||
|
||||
public abstract boolean isAddNotNullAssertions();
|
||||
|
||||
+17
-13
@@ -124,19 +124,7 @@ public abstract class OrderEntryFix implements IntentionAction, LocalQuickFix {
|
||||
final VirtualFile location = PsiUtilCore.getVirtualFile(reference != null ? reference.getElement() : null);
|
||||
boolean inTests = location != null && ModuleRootManager.getInstance(currentModule).getFileIndex().isInTestSourceContent(location);
|
||||
try {
|
||||
final String[] junit4Paths = {JavaSdkUtil.getJunit4JarPath(),
|
||||
PathUtil.getJarPathForClass(Class.forName("org.hamcrest.Matcher")),
|
||||
PathUtil.getJarPathForClass(Class.forName("org.hamcrest.Matchers"))};
|
||||
ModuleRootModificationUtil.addModuleLibrary(currentModule,
|
||||
"JUnit4",
|
||||
ContainerUtil.map(junit4Paths,
|
||||
new Function<String, String>() {
|
||||
@Override
|
||||
public String fun(String libPath) {
|
||||
return convertToLibraryRoot(libPath).getUrl();
|
||||
}
|
||||
}),
|
||||
Collections.<String>emptyList(), inTests ? DependencyScope.TEST : DependencyScope.COMPILE);
|
||||
addJUnit4Library(inTests, currentModule);
|
||||
final GlobalSearchScope scope = GlobalSearchScope.moduleWithLibrariesScope(currentModule);
|
||||
final PsiClass aClass = JavaPsiFacade.getInstance(project).findClass(className, scope);
|
||||
if (aClass != null && editor != null && reference != null) {
|
||||
@@ -276,6 +264,22 @@ public abstract class OrderEntryFix implements IntentionAction, LocalQuickFix {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void addJUnit4Library(boolean inTests, Module currentModule) throws ClassNotFoundException {
|
||||
final String[] junit4Paths = {JavaSdkUtil.getJunit4JarPath(),
|
||||
PathUtil.getJarPathForClass(Class.forName("org.hamcrest.Matcher")),
|
||||
PathUtil.getJarPathForClass(Class.forName("org.hamcrest.Matchers"))};
|
||||
ModuleRootModificationUtil.addModuleLibrary(currentModule,
|
||||
"JUnit4",
|
||||
ContainerUtil.map(junit4Paths,
|
||||
new Function<String, String>() {
|
||||
@Override
|
||||
public String fun(String libPath) {
|
||||
return convertToLibraryRoot(libPath).getUrl();
|
||||
}
|
||||
}),
|
||||
Collections.<String>emptyList(), inTests ? DependencyScope.TEST : DependencyScope.COMPILE);
|
||||
}
|
||||
|
||||
private static List<PsiClass> filterAllowedDependencies(PsiElement element, PsiClass[] classes) {
|
||||
DependencyValidationManager dependencyValidationManager = DependencyValidationManager.getInstance(element.getProject());
|
||||
PsiFile fromFile = element.getContainingFile();
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.testIntegration;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.OrderEntryFix;
|
||||
import com.intellij.ide.fileTemplates.FileTemplate;
|
||||
import com.intellij.ide.fileTemplates.FileTemplateDescriptor;
|
||||
import com.intellij.ide.fileTemplates.FileTemplateManager;
|
||||
@@ -119,4 +120,8 @@ public abstract class JavaTestFramework implements TestFramework {
|
||||
public FileTemplateDescriptor getTestClassFileTemplateDescriptor() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setupLibrary(Module module) {
|
||||
OrderEntryFix.addJarToRoots(getLibraryPath(), module, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,10 +126,7 @@ public class CreateTestDialog extends DialogWrapper {
|
||||
for (final TestFramework descriptor : Extensions.getExtensions(TestFramework.EXTENSION_NAME)) {
|
||||
final JRadioButton b = new JRadioButton(descriptor.getName());
|
||||
if (descriptor instanceof JavaTestFramework) {
|
||||
final char mnemonic = ((JavaTestFramework)descriptor).getMnemonic();
|
||||
if (mnemonic > -1) {
|
||||
b.setMnemonic(mnemonic);
|
||||
}
|
||||
b.setMnemonic(((JavaTestFramework)descriptor).getMnemonic());
|
||||
}
|
||||
myLibraryButtons.add(b);
|
||||
group.add(b);
|
||||
@@ -173,7 +170,11 @@ public class CreateTestDialog extends DialogWrapper {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
OrderEntryFix.addJarToRoots(mySelectedFramework.getLibraryPath(), myTargetModule, null);
|
||||
if (mySelectedFramework instanceof JavaTestFramework) {
|
||||
((JavaTestFramework)mySelectedFramework).setupLibrary(myTargetModule);
|
||||
} else {
|
||||
OrderEntryFix.addJarToRoots(mySelectedFramework.getLibraryPath(), myTargetModule, null);
|
||||
}
|
||||
}
|
||||
});
|
||||
myFixLibraryPanel.setVisible(false);
|
||||
|
||||
+1
-40
@@ -97,8 +97,8 @@ public abstract class AbstractLayoutCodeProcessorTest extends PsiTestCase {
|
||||
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
super.tearDown();
|
||||
delete(myWorkingDirectory.getVirtualFile());
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -277,45 +277,6 @@ public abstract class AbstractLayoutCodeProcessorTest extends PsiTestCase {
|
||||
PsiTestUtil.addSourceRoot(module, src.getVirtualFile());
|
||||
return module;
|
||||
}
|
||||
|
||||
class TestFileStructure {
|
||||
private int myLevel;
|
||||
@NotNull private PsiDirectory myRoot;
|
||||
@NotNull private PsiDirectory myCurrentLevelDirectory;
|
||||
private List<List<PsiFile>> myFilesForLevel = new ArrayList<List<PsiFile>>();
|
||||
|
||||
TestFileStructure(@NotNull PsiDirectory root) {
|
||||
myRoot = root;
|
||||
myCurrentLevelDirectory = root;
|
||||
myFilesForLevel.add(new ArrayList<PsiFile>());
|
||||
myLevel = 0;
|
||||
}
|
||||
|
||||
TestFileStructure addTestFilesToCurrentDirectory(String[] names) throws IOException {
|
||||
getFilesAtLevel(myLevel).addAll(createTestFiles(myCurrentLevelDirectory, names));
|
||||
return this;
|
||||
}
|
||||
|
||||
TestFileStructure createDirectoryAndMakeItCurrent(String name) {
|
||||
myLevel++;
|
||||
myFilesForLevel.add(new ArrayList<PsiFile>());
|
||||
myCurrentLevelDirectory = createDirectory(myCurrentLevelDirectory.getVirtualFile(), name);
|
||||
return this;
|
||||
}
|
||||
|
||||
List<PsiFile> getFilesAtLevel(int level) {
|
||||
assert (myLevel >= level);
|
||||
return myFilesForLevel.get(level);
|
||||
}
|
||||
|
||||
List<PsiFile> getAllFiles() {
|
||||
List<PsiFile> all = new ArrayList<PsiFile>();
|
||||
for (List<PsiFile> files: myFilesForLevel) {
|
||||
all.addAll(files);
|
||||
}
|
||||
return all;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+21
-8
@@ -32,14 +32,6 @@ public class ReformatCodeActionTest extends AbstractLayoutCodeProcessorTest {
|
||||
|
||||
private static String[] classNames = {"Vasya", "Main", "Oiie", "Ololo"};
|
||||
|
||||
private TestFileStructure getThreeLevelDirectoryStructure() throws IOException {
|
||||
TestFileStructure fileStructure = new TestFileStructure(getTempRootDirectory());
|
||||
fileStructure.createDirectoryAndMakeItCurrent("dir").addTestFilesToCurrentDirectory(classNames)
|
||||
.createDirectoryAndMakeItCurrent("innerDir").addTestFilesToCurrentDirectory(classNames)
|
||||
.createDirectoryAndMakeItCurrent("innerInnerDir").addTestFilesToCurrentDirectory(classNames);
|
||||
return fileStructure;
|
||||
}
|
||||
|
||||
public void testReformatAndOptimizeMultipleFiles() throws IOException {
|
||||
List<PsiFile> files = createTestFiles(getTempRootDirectory(), classNames);
|
||||
injectMockDialogFlags(new MockReformatFileSettings().setOptimizeImports(true));
|
||||
@@ -118,4 +110,25 @@ public class ReformatCodeActionTest extends AbstractLayoutCodeProcessorTest {
|
||||
checkFormationAndImportsOptimizationFor(files);
|
||||
}
|
||||
|
||||
private TestFileStructure getThreeLevelDirectoryStructure() throws IOException {
|
||||
TestFileStructure fileStructure = new TestFileStructure(getModule(), getTempRootDirectory());
|
||||
|
||||
fileStructure.createDirectoryAndMakeItCurrent("dir");
|
||||
addFilesToCurrentDirectory(fileStructure);
|
||||
|
||||
fileStructure.createDirectoryAndMakeItCurrent("innerDir");
|
||||
addFilesToCurrentDirectory(fileStructure);
|
||||
|
||||
fileStructure.createDirectoryAndMakeItCurrent("innerInnerDir");
|
||||
addFilesToCurrentDirectory(fileStructure);
|
||||
|
||||
return fileStructure;
|
||||
}
|
||||
|
||||
private void addFilesToCurrentDirectory(TestFileStructure fileStructure) throws IOException {
|
||||
for (int i = 0; i < 5; i++) {
|
||||
String className = "Test" + i;
|
||||
fileStructure.addTestFile("Test" + i + ".java", getUntouchedJavaSourceForTotalProcessing(className));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ public class DeprecationInspectionTest extends InspectionTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testDeprecatedDefaultConstructorFromTypeParameter() throws Exception {
|
||||
public void testDeprecatedDefaultConstructorTypeParameter() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -16,13 +16,12 @@
|
||||
|
||||
package com.intellij.psi.impl.source;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.CommonClassNames;
|
||||
import com.intellij.util.CharTable;
|
||||
import com.intellij.util.containers.OpenTHashSet;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
import com.intellij.util.text.CharSequenceHashingStrategy;
|
||||
import com.intellij.util.text.CharSequenceSubSequence;
|
||||
import com.intellij.util.text.StringFactory;
|
||||
import gnu.trove.TIntObjectHashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -34,55 +33,62 @@ import java.lang.reflect.Modifier;
|
||||
*/
|
||||
public class CharTableImpl implements CharTable {
|
||||
private static final int INTERN_THRESHOLD = 40; // 40 or more characters long tokens won't be interned.
|
||||
private static final CharSequenceHashingStrategy HASHER = CharSequenceHashingStrategy.CASE_SENSITIVE;
|
||||
private static final OpenTHashSet<CharSequence> STATIC_ENTRIES = newStaticSet();
|
||||
|
||||
private final OpenTHashSet<CharSequence> entries = new OpenTHashSet<CharSequence>(10, 0.9f, HASHER);
|
||||
private static final StringHashToCharSequencesMap STATIC_ENTRIES = newStaticSet();
|
||||
private final StringHashToCharSequencesMap entries = new StringHashToCharSequencesMap(10, 0.9f);
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public CharSequence intern(@NotNull final CharSequence text) {
|
||||
if (text.length() > INTERN_THRESHOLD) return createSequence(text);
|
||||
CharSequence result;
|
||||
if (text.length() > INTERN_THRESHOLD) result = createSequence(text);
|
||||
else result = doIntern(text);
|
||||
|
||||
return doIntern(text);
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CharSequence doIntern(@NotNull CharSequence text) {
|
||||
CharSequence interned = getStaticInterned(text);
|
||||
private CharSequence doIntern(@NotNull CharSequence text, int startOffset, int endOffset) {
|
||||
int hashCode = subSequenceHashCode(text, startOffset, endOffset);
|
||||
CharSequence interned = STATIC_ENTRIES.getSubSequenceWithHashCode(hashCode, text, startOffset, endOffset);
|
||||
if (interned != null) {
|
||||
return interned;
|
||||
}
|
||||
|
||||
synchronized(entries) {
|
||||
interned = entries.get(text);
|
||||
if (interned != null) {
|
||||
return interned;
|
||||
}
|
||||
|
||||
// We need to create separate string just to prevent referencing all character data when original is string or char sequence over string
|
||||
final CharSequence entry = createSequence(text);
|
||||
boolean added = entries.add(entry);
|
||||
assert added;
|
||||
|
||||
return entry;
|
||||
return entries.getOrAddSubSequenceWithHashCode(hashCode, text, startOffset, endOffset);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CharSequence doIntern(@NotNull CharSequence text) {
|
||||
return doIntern(text, 0, text.length());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public CharSequence intern(@NotNull final CharSequence baseText, final int startOffset, final int endOffset) {
|
||||
if (endOffset - startOffset == baseText.length()) return intern(baseText);
|
||||
return intern(new CharSequenceSubSequence(baseText, startOffset, endOffset));
|
||||
CharSequence result;
|
||||
if (endOffset - startOffset == baseText.length()) result = intern(baseText);
|
||||
else if (endOffset - startOffset > INTERN_THRESHOLD) result = createSequence(baseText, startOffset, endOffset);
|
||||
else result = doIntern(baseText, startOffset, endOffset);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String createSequence(@NotNull CharSequence text) {
|
||||
return createSequence(text, 0, text.length());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String createSequence(@NotNull CharSequence text, int startOffset, int endOffset) {
|
||||
if (text instanceof String) {
|
||||
return (String)text;
|
||||
return ((String)text).substring(startOffset, endOffset);
|
||||
}
|
||||
char[] buf = new char[text.length()];
|
||||
CharArrayUtil.getChars(text, buf, 0);
|
||||
char[] buf = new char[endOffset - startOffset];
|
||||
CharArrayUtil.getChars(text, buf, startOffset, 0, buf.length);
|
||||
return StringFactory.createShared(buf); // this way the .toString() doesn't create another instance (as opposed to new CharArrayCharSequence())
|
||||
}
|
||||
|
||||
@@ -96,9 +102,9 @@ public class CharTableImpl implements CharTable {
|
||||
STATIC_ENTRIES.add(text);
|
||||
}
|
||||
}
|
||||
|
||||
private static OpenTHashSet<CharSequence> newStaticSet() {
|
||||
final OpenTHashSet<CharSequence> r = new OpenTHashSet<CharSequence>(10, 0.9f, HASHER);
|
||||
|
||||
private static StringHashToCharSequencesMap newStaticSet() {
|
||||
final StringHashToCharSequencesMap r = new StringHashToCharSequencesMap(10, 0.9f);
|
||||
r.add("==" );
|
||||
r.add("!=" );
|
||||
r.add("||" );
|
||||
@@ -214,4 +220,95 @@ public class CharTableImpl implements CharTable {
|
||||
staticIntern(typeName);
|
||||
}
|
||||
}
|
||||
|
||||
private static class StringHashToCharSequencesMap extends TIntObjectHashMap<Object> {
|
||||
StringHashToCharSequencesMap(int capacity, float loadFactor) {
|
||||
super(capacity, loadFactor);
|
||||
}
|
||||
|
||||
CharSequence get(CharSequence sequence, int startOffset, int endOffset) {
|
||||
return getSubSequenceWithHashCode(subSequenceHashCode(sequence, startOffset, endOffset), sequence, startOffset, endOffset);
|
||||
}
|
||||
|
||||
CharSequence getSubSequenceWithHashCode(int hashCode, CharSequence sequence, int startOffset, int endOffset) {
|
||||
Object o = get(hashCode);
|
||||
if (o == null) return null;
|
||||
if (o instanceof CharSequence) {
|
||||
if (charSequenceSubSequenceEquals((CharSequence)o, sequence, startOffset, endOffset)) {
|
||||
return (CharSequence)o;
|
||||
}
|
||||
return null;
|
||||
} else if (o instanceof CharSequence[]) {
|
||||
for(CharSequence cs:(CharSequence[])o) {
|
||||
if (charSequenceSubSequenceEquals(cs, sequence, startOffset, endOffset)) {
|
||||
return cs;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
assert false:o.getClass();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static boolean charSequenceSubSequenceEquals(CharSequence cs, CharSequence baseSequence, int startOffset, int endOffset) {
|
||||
if (cs.length() != endOffset - startOffset) return false;
|
||||
if (cs == baseSequence && startOffset == 0) return true;
|
||||
for(int i = 0, len = cs.length(); i < len; ++i) {
|
||||
if (cs.charAt(i) != baseSequence.charAt(startOffset + i)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
CharSequence get(CharSequence sequence) {
|
||||
return get(sequence, 0, sequence.length());
|
||||
}
|
||||
|
||||
CharSequence add(CharSequence sequence) {
|
||||
return add(sequence, 0, sequence.length());
|
||||
}
|
||||
|
||||
CharSequence add(CharSequence sequence, int startOffset, int endOffset) {
|
||||
int hashCode = subSequenceHashCode(sequence, startOffset, endOffset);
|
||||
return getOrAddSubSequenceWithHashCode(hashCode, sequence, startOffset, endOffset);
|
||||
}
|
||||
|
||||
private CharSequence getOrAddSubSequenceWithHashCode(int hashCode, CharSequence sequence, int startOffset, int endOffset) {
|
||||
int index = index(hashCode);
|
||||
String addedSequence = null;
|
||||
|
||||
if (index < 0) {
|
||||
put(hashCode, addedSequence = createSequence(sequence, startOffset, endOffset));
|
||||
} else {
|
||||
Object value = _values[index];
|
||||
if (value instanceof CharSequence) {
|
||||
CharSequence existingSequence = (CharSequence)value;
|
||||
if (charSequenceSubSequenceEquals(existingSequence, sequence, startOffset, endOffset)) {
|
||||
return existingSequence;
|
||||
}
|
||||
put(hashCode, new CharSequence[] {existingSequence, addedSequence = createSequence(sequence, startOffset, endOffset)});
|
||||
} else if (value instanceof CharSequence[]) {
|
||||
CharSequence[] existingSequenceArray = (CharSequence[])value;
|
||||
for(CharSequence cs:existingSequenceArray) {
|
||||
if (charSequenceSubSequenceEquals(cs, sequence, startOffset, endOffset)) {
|
||||
return cs;
|
||||
}
|
||||
}
|
||||
CharSequence[] newSequenceArray = new CharSequence[existingSequenceArray.length + 1];
|
||||
System.arraycopy(existingSequenceArray, 0, newSequenceArray, 0, existingSequenceArray.length);
|
||||
newSequenceArray[existingSequenceArray.length] = addedSequence = createSequence(sequence, startOffset, endOffset);
|
||||
put(hashCode, newSequenceArray);
|
||||
} else {
|
||||
assert false:value.getClass();
|
||||
}
|
||||
}
|
||||
return addedSequence;
|
||||
}
|
||||
}
|
||||
|
||||
private static int subSequenceHashCode(CharSequence sequence, int startOffset, int endOffset) {
|
||||
if (startOffset == 0 && endOffset == sequence.length()) {
|
||||
return StringUtil.stringHashCode(sequence);
|
||||
}
|
||||
return StringUtil.stringHashCode(sequence, startOffset, endOffset);
|
||||
}
|
||||
}
|
||||
|
||||
+45
-73
@@ -25,7 +25,6 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
@@ -34,18 +33,23 @@ import com.intellij.openapi.project.IndexNotReadyException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectCoreUtil;
|
||||
import com.intellij.openapi.roots.GeneratedSourcesFilter;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.ui.ex.MessagesEx;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.PsiBundle;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.SequentialModalProgressTask;
|
||||
import com.intellij.util.SequentialTask;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.FutureTask;
|
||||
@@ -205,7 +209,14 @@ public abstract class AbstractLayoutCodeProcessor {
|
||||
return;
|
||||
}
|
||||
|
||||
FileTreeIterator iterator = buildFileTreeIterator();
|
||||
FileTreeIterator iterator;
|
||||
if (myFiles != null) {
|
||||
iterator = new FileTreeIterator(myFiles);
|
||||
}
|
||||
else {
|
||||
iterator = myProcessChangedTextOnly ? buildChangedFilesIterator()
|
||||
: buildFileTreeIterator();
|
||||
}
|
||||
runProcessFiles(iterator);
|
||||
}
|
||||
|
||||
@@ -226,6 +237,35 @@ public abstract class AbstractLayoutCodeProcessor {
|
||||
return new FileTreeIterator(Collections.<PsiFile>emptyList());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private FileTreeIterator buildChangedFilesIterator() {
|
||||
List<PsiFile> files = getChangedFilesFromContext();
|
||||
return new FileTreeIterator(files);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<PsiFile> getChangedFilesFromContext() {
|
||||
List<PsiDirectory> dirs = getAllSearchableDirsFromContext();
|
||||
return FormatChangedTextUtil.getChangedFilesFromDirs(myProject, dirs);
|
||||
}
|
||||
|
||||
private List<PsiDirectory> getAllSearchableDirsFromContext() {
|
||||
List<PsiDirectory> dirs = ContainerUtil.newArrayList();
|
||||
if (myDirectory != null) {
|
||||
dirs.add(myDirectory);
|
||||
}
|
||||
else if (myModule != null) {
|
||||
List<PsiDirectory> allModuleDirs = FileTreeIterator.collectModuleDirectories(myModule);
|
||||
dirs.addAll(allModuleDirs);
|
||||
}
|
||||
else if (myProject != null) {
|
||||
List<PsiDirectory> allProjectDirs = FileTreeIterator.collectProjectDirectories(myProject);
|
||||
dirs.addAll(allProjectDirs);
|
||||
}
|
||||
return dirs;
|
||||
}
|
||||
|
||||
|
||||
private void runProcessFile(@NotNull final PsiFile file) {
|
||||
Document document = PsiDocumentManager.getInstance(myProject).getDocument(file);
|
||||
|
||||
@@ -493,72 +533,4 @@ public abstract class AbstractLayoutCodeProcessor {
|
||||
myCompositeTask = compositeTask;
|
||||
}
|
||||
}
|
||||
|
||||
private static class FileTreeIterator {
|
||||
private Queue<PsiFile> myCurrentFiles = new LinkedList<PsiFile>();
|
||||
private Queue<PsiDirectory> myCurrentDirectories = new LinkedList<PsiDirectory>();
|
||||
|
||||
public FileTreeIterator(@NotNull List<PsiFile> files) {
|
||||
myCurrentFiles.addAll(files);
|
||||
}
|
||||
|
||||
public FileTreeIterator(@NotNull Module module) {
|
||||
addDirectoriesFrom(module);
|
||||
expandDirectoriesUntilFilesNotEmpty();
|
||||
}
|
||||
|
||||
public FileTreeIterator(@NotNull Project project) {
|
||||
Module[] modules = ModuleManager.getInstance(project).getModules();
|
||||
for (Module module : modules) {
|
||||
addDirectoriesFrom(module);
|
||||
}
|
||||
expandDirectoriesUntilFilesNotEmpty();
|
||||
}
|
||||
|
||||
public FileTreeIterator(@NotNull PsiDirectory directory) {
|
||||
myCurrentDirectories.add(directory);
|
||||
expandDirectoriesUntilFilesNotEmpty();
|
||||
}
|
||||
|
||||
public FileTreeIterator(@NotNull FileTreeIterator fileTreeIterator) {
|
||||
myCurrentFiles = new LinkedList<PsiFile>(fileTreeIterator.myCurrentFiles);
|
||||
myCurrentDirectories = new LinkedList<PsiDirectory>(fileTreeIterator.myCurrentDirectories);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiFile next() {
|
||||
if (myCurrentFiles.isEmpty()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
PsiFile current = myCurrentFiles.poll();
|
||||
expandDirectoriesUntilFilesNotEmpty();
|
||||
return current;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return !myCurrentFiles.isEmpty();
|
||||
}
|
||||
|
||||
private void expandDirectoriesUntilFilesNotEmpty() {
|
||||
while (myCurrentFiles.isEmpty() && !myCurrentDirectories.isEmpty()) {
|
||||
PsiDirectory dir = myCurrentDirectories.poll();
|
||||
expandDirectory(dir);
|
||||
}
|
||||
}
|
||||
|
||||
private void expandDirectory(@NotNull PsiDirectory dir) {
|
||||
Collections.addAll(myCurrentFiles, dir.getFiles());
|
||||
Collections.addAll(myCurrentDirectories, dir.getSubdirectories());
|
||||
}
|
||||
|
||||
private void addDirectoriesFrom(Module module) {
|
||||
VirtualFile[] contentRoots = ModuleRootManager.getInstance(module).getContentRoots();
|
||||
for (VirtualFile root : contentRoots) {
|
||||
PsiDirectory dir = PsiManager.getInstance(module.getProject()).findDirectory(root);
|
||||
if (dir != null) {
|
||||
myCurrentDirectories.add(dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.codeInsight.actions;
|
||||
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class FileTreeIterator {
|
||||
private Queue<PsiFile> myCurrentFiles = new LinkedList<PsiFile>();
|
||||
private Queue<PsiDirectory> myCurrentDirectories = new LinkedList<PsiDirectory>();
|
||||
|
||||
public FileTreeIterator(@NotNull List<PsiFile> files) {
|
||||
myCurrentFiles.addAll(files);
|
||||
}
|
||||
|
||||
public FileTreeIterator(@NotNull Module module) {
|
||||
myCurrentDirectories.addAll(collectModuleDirectories(module));
|
||||
expandDirectoriesUntilFilesNotEmpty();
|
||||
}
|
||||
|
||||
public FileTreeIterator(@NotNull Project project) {
|
||||
myCurrentDirectories.addAll(collectProjectDirectories(project));
|
||||
expandDirectoriesUntilFilesNotEmpty();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<PsiDirectory> collectProjectDirectories(@NotNull Project project) {
|
||||
List<PsiDirectory> directories = ContainerUtil.newArrayList();
|
||||
|
||||
Module[] modules = ModuleManager.getInstance(project).getModules();
|
||||
for (Module module : modules) {
|
||||
directories.addAll(collectModuleDirectories(module));
|
||||
}
|
||||
|
||||
return directories;
|
||||
}
|
||||
|
||||
public FileTreeIterator(@NotNull PsiDirectory directory) {
|
||||
myCurrentDirectories.add(directory);
|
||||
expandDirectoriesUntilFilesNotEmpty();
|
||||
}
|
||||
|
||||
public FileTreeIterator(@NotNull FileTreeIterator fileTreeIterator) {
|
||||
myCurrentFiles = new LinkedList<PsiFile>(fileTreeIterator.myCurrentFiles);
|
||||
myCurrentDirectories = new LinkedList<PsiDirectory>(fileTreeIterator.myCurrentDirectories);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiFile next() {
|
||||
if (myCurrentFiles.isEmpty()) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
PsiFile current = myCurrentFiles.poll();
|
||||
expandDirectoriesUntilFilesNotEmpty();
|
||||
return current;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return !myCurrentFiles.isEmpty();
|
||||
}
|
||||
|
||||
private void expandDirectoriesUntilFilesNotEmpty() {
|
||||
while (myCurrentFiles.isEmpty() && !myCurrentDirectories.isEmpty()) {
|
||||
PsiDirectory dir = myCurrentDirectories.poll();
|
||||
expandDirectory(dir);
|
||||
}
|
||||
}
|
||||
|
||||
private void expandDirectory(@NotNull PsiDirectory dir) {
|
||||
Collections.addAll(myCurrentFiles, dir.getFiles());
|
||||
Collections.addAll(myCurrentDirectories, dir.getSubdirectories());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<PsiDirectory> collectModuleDirectories(Module module) {
|
||||
List<PsiDirectory> dirs = ContainerUtil.newArrayList();
|
||||
|
||||
VirtualFile[] contentRoots = ModuleRootManager.getInstance(module).getContentRoots();
|
||||
for (VirtualFile root : contentRoots) {
|
||||
PsiDirectory dir = PsiManager.getInstance(module.getProject()).findDirectory(root);
|
||||
if (dir != null) {
|
||||
dirs.add(dir);
|
||||
}
|
||||
}
|
||||
|
||||
return dirs;
|
||||
}
|
||||
}
|
||||
+111
-6
@@ -17,7 +17,9 @@ package com.intellij.codeInsight.actions;
|
||||
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.EditorFactory;
|
||||
import com.intellij.openapi.editor.markup.RangeHighlighter;
|
||||
import com.intellij.openapi.module.ModifiableModuleModel;
|
||||
import com.intellij.openapi.module.Module;
|
||||
@@ -25,27 +27,30 @@ import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.changes.Change;
|
||||
import com.intellij.openapi.vcs.changes.ChangeListManager;
|
||||
import com.intellij.openapi.vcs.changes.ContentRevision;
|
||||
import com.intellij.openapi.vcs.ex.LineStatusTracker;
|
||||
import com.intellij.openapi.vcs.ex.Range;
|
||||
import com.intellij.openapi.vcs.ex.RangesBuilder;
|
||||
import com.intellij.openapi.vcs.impl.LineStatusTrackerManager;
|
||||
import com.intellij.openapi.vcs.impl.LineStatusTrackerManagerI;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.ContainerUtilRt;
|
||||
import com.intellij.util.diff.FilesTooBigForDiffException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Contains utility methods for 'format only changed text' (in terms of VCS changes).
|
||||
*
|
||||
* @author Denis Zhdanov
|
||||
* @since 12/19/11 10:55 AM
|
||||
*/
|
||||
public class FormatChangedTextUtil {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.actions.FormatChangedTextUtil");
|
||||
|
||||
private FormatChangedTextUtil() {
|
||||
}
|
||||
@@ -120,6 +125,14 @@ public class FormatChangedTextUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean hasChanges(@NotNull VirtualFile[] files, @NotNull Project project) {
|
||||
for (VirtualFile file : files) {
|
||||
if (hasChanges(file, project))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows to answer if any file that belongs to the given module has changes in comparison with VCS.
|
||||
*
|
||||
@@ -209,4 +222,96 @@ public class FormatChangedTextUtil {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<PsiFile> getChangedFilesFromDirs(@NotNull Project project, @NotNull List<PsiDirectory> dirs) {
|
||||
ChangeListManager changeListManager = ChangeListManager.getInstance(project);
|
||||
Collection<Change> changes = ContainerUtil.newArrayList();
|
||||
|
||||
for (PsiDirectory dir : dirs) {
|
||||
changes.addAll(changeListManager.getChangesIn(dir.getVirtualFile()));
|
||||
}
|
||||
|
||||
return getChangedFiles(project, changes);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<PsiFile> getChangedFiles(@NotNull Project project, @NotNull Collection<Change> changes) {
|
||||
List<PsiFile> files = ContainerUtil.newArrayList();
|
||||
for (Change change : changes) {
|
||||
VirtualFile vFile = change.getVirtualFile();
|
||||
if (vFile != null) {
|
||||
PsiFile file = PsiManager.getInstance(project).findFile(vFile);
|
||||
if (file != null) files.add(file);
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<TextRange> getChangedTextRanges(@NotNull Project project, @NotNull PsiFile file) {
|
||||
Change change = ChangeListManager.getInstance(project).getChange(file.getVirtualFile());
|
||||
if (change == null) {
|
||||
return ContainerUtilRt.emptyList();
|
||||
}
|
||||
if (change.getType() == Change.Type.NEW) {
|
||||
return ContainerUtil.newArrayList(file.getTextRange());
|
||||
}
|
||||
|
||||
String contentFromVcs = getRevisionedContentFrom(change);
|
||||
return contentFromVcs != null ? calculateChangedTextRanges(project, file, contentFromVcs)
|
||||
: ContainerUtil.<TextRange>emptyList();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getRevisionedContentFrom(@NotNull Change change) {
|
||||
ContentRevision revision = change.getBeforeRevision();
|
||||
if (revision == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return revision.getContent();
|
||||
}
|
||||
catch (VcsException e) {
|
||||
LOG.error("Can't get content for: " + change.getVirtualFile(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<TextRange> calculateChangedTextRanges(@NotNull Project project, @NotNull PsiFile file, @NotNull String contentFromVcs) {
|
||||
Document documentFromVcs = EditorFactory.getInstance().createDocument(contentFromVcs);
|
||||
Document document = PsiDocumentManager.getInstance(project).getDocument(file);
|
||||
|
||||
if (document == null) {
|
||||
return ContainerUtil.emptyList();
|
||||
}
|
||||
|
||||
try {
|
||||
List<Range> changedRanges = new RangesBuilder(document, documentFromVcs).getRanges();
|
||||
return getChangedTextRanges(document, changedRanges);
|
||||
}
|
||||
catch (FilesTooBigForDiffException e) {
|
||||
LOG.error("Error while calculating changed ranges for: " + file.getVirtualFile(), e);
|
||||
return ContainerUtil.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static List<TextRange> getChangedTextRanges(@NotNull Document document, @NotNull List<Range> changedRanges) {
|
||||
List<TextRange> ranges = ContainerUtil.newArrayList();
|
||||
for (Range range : changedRanges) {
|
||||
if (range.getType() != Range.DELETED) {
|
||||
int changeStartLine = range.getOffset1();
|
||||
int changeEndLine = range.getOffset2();
|
||||
|
||||
int lineStartOffset = document.getLineStartOffset(changeStartLine);
|
||||
int lineEndOffset = document.getLineEndOffset(changeEndLine - 1);
|
||||
|
||||
ranges.add(new TextRange(lineStartOffset, lineEndOffset));
|
||||
}
|
||||
}
|
||||
return ranges;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,8 +187,7 @@ public class LayoutCodeDialog extends DialogWrapper implements LayoutCodeOptions
|
||||
myCbArrangeEntries.setEnabled(true);
|
||||
myCbArrangeEntries.setSelected(myRearrangeEntriesSelected);
|
||||
|
||||
//TODO enable it when getting changed ranges will be fixed
|
||||
myCbOnlyVcsChangedRegions.setEnabled(false);
|
||||
myCbOnlyVcsChangedRegions.setEnabled(myDirectory != null && FormatChangedTextUtil.hasChanges(myDirectory));
|
||||
myCbOnlyVcsChangedRegions.setSelected(false);
|
||||
|
||||
myDoNotAskMeCheckBox.setEnabled(false);
|
||||
|
||||
+14
-2
@@ -34,11 +34,13 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi
|
||||
private static @NonNls final String HELP_ID = "editing.codeReformatting";
|
||||
|
||||
private final String myText;
|
||||
private final boolean myEnableOnlyVCSChangedTextCb;
|
||||
private final boolean mySuggestOptimizeImports;
|
||||
private final Project myProject;
|
||||
|
||||
|
||||
private JCheckBox myCbOptimizeImports;
|
||||
private JCheckBox myCbOnlyVcsChangedRegions;
|
||||
private JCheckBox myCbRearrangeEntries;
|
||||
|
||||
public LayoutProjectCodeDialog(@NotNull Project project,
|
||||
@@ -51,6 +53,7 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi
|
||||
myText = text;
|
||||
mySuggestOptimizeImports = suggestOptimizeImports;
|
||||
myProject = project;
|
||||
myEnableOnlyVCSChangedTextCb = enableOnlyVCSChangedTextCb;
|
||||
|
||||
setOKButtonText(CodeInsightBundle.message("reformat.code.accept.button.text"));
|
||||
setTitle(title);
|
||||
@@ -63,16 +66,22 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi
|
||||
return new JLabel(myText);
|
||||
}
|
||||
|
||||
JPanel panel = new JPanel(new GridLayout(3, 1));
|
||||
JPanel panel = new JPanel(new GridLayout(4, 1));
|
||||
myCbOptimizeImports = new JCheckBox(CodeInsightBundle.message("reformat.option.optimize.imports"));
|
||||
myCbRearrangeEntries = new JCheckBox(CodeInsightBundle.message("reformat.option.rearrange.entries"));
|
||||
myCbOnlyVcsChangedRegions = new JCheckBox(CodeInsightBundle.message("reformat.option.vcs.changed.region"));
|
||||
|
||||
panel.add(new JLabel(myText));
|
||||
panel.add(myCbOptimizeImports);
|
||||
panel.add(myCbRearrangeEntries);
|
||||
panel.add(myCbOnlyVcsChangedRegions);
|
||||
|
||||
myCbOptimizeImports.setSelected(PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, false));
|
||||
myCbRearrangeEntries.setSelected(LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(myProject));
|
||||
myCbOnlyVcsChangedRegions.setEnabled(myEnableOnlyVCSChangedTextCb);
|
||||
myCbOnlyVcsChangedRegions.setSelected(
|
||||
myEnableOnlyVCSChangedTextCb && PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false)
|
||||
);
|
||||
|
||||
return panel;
|
||||
}
|
||||
@@ -99,6 +108,9 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi
|
||||
if (mySuggestOptimizeImports) {
|
||||
PropertiesComponent.getInstance().setValue(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, Boolean.toString(isOptimizeImports()));
|
||||
LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, isRearrangeEntries());
|
||||
if (myEnableOnlyVCSChangedTextCb) {
|
||||
PropertiesComponent.getInstance().setValue(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, Boolean.toString(myCbOnlyVcsChangedRegions.isSelected()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +119,7 @@ public class LayoutProjectCodeDialog extends DialogWrapper implements ReformatFi
|
||||
}
|
||||
|
||||
public boolean isProcessOnlyChangedText() {
|
||||
return false;
|
||||
return myCbOnlyVcsChangedRegions.isEnabled() && myCbOnlyVcsChangedRegions.isSelected();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+15
-10
@@ -26,6 +26,7 @@ import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -62,14 +63,14 @@ public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
public ReformatCodeProcessor(Project project, PsiFile[] files, Runnable postRunnable, boolean processChangedTextOnly) {
|
||||
public ReformatCodeProcessor(Project project, PsiFile[] files, @Nullable Runnable postRunnable, boolean processChangedTextOnly) {
|
||||
this(project, files, COMMAND_NAME, postRunnable, processChangedTextOnly);
|
||||
}
|
||||
|
||||
public ReformatCodeProcessor(Project project,
|
||||
PsiFile[] files,
|
||||
String commandName,
|
||||
Runnable postRunnable,
|
||||
@Nullable Runnable postRunnable,
|
||||
boolean processChangedTextOnly)
|
||||
{
|
||||
super(project, files, PROGRESS_TEXT, commandName, postRunnable, processChangedTextOnly);
|
||||
@@ -85,13 +86,8 @@ public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor {
|
||||
public Boolean call() throws Exception {
|
||||
FormattingProgressTask.FORMATTING_CANCELLED_FLAG.set(false);
|
||||
try {
|
||||
if (myRanges.isEmpty() && processChangedTextOnly) {
|
||||
myRanges.addAll(FormatChangedTextUtil.getChanges(file));
|
||||
}
|
||||
if (myRanges.isEmpty()) {
|
||||
myRanges.add(file.getTextRange());
|
||||
}
|
||||
CodeStyleManager.getInstance(myProject).reformatText(file, myRanges);
|
||||
Collection<TextRange> ranges = getRangesToFormat(processChangedTextOnly, file);
|
||||
CodeStyleManager.getInstance(myProject).reformatText(file, ranges);
|
||||
return !FormattingProgressTask.FORMATTING_CANCELLED_FLAG.get();
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
@@ -104,4 +100,13 @@ public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor {
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Collection<TextRange> getRangesToFormat(boolean processChangedTextOnly, PsiFile file) {
|
||||
if (processChangedTextOnly) {
|
||||
return FormatChangedTextUtil.getChangedTextRanges(myProject, file);
|
||||
}
|
||||
|
||||
return !myRanges.isEmpty() ? myRanges : ContainerUtil.newArrayList(file.getTextRange());
|
||||
}
|
||||
}
|
||||
@@ -3,12 +3,12 @@
|
||||
<grid id="59847" binding="myPanel" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="4" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="30" y="17" width="244" height="113"/>
|
||||
<xy x="30" y="17" width="244" height="149"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<grid id="e83d0" layout-manager="GridLayoutManager" row-count="4" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<grid id="e83d0" layout-manager="GridLayoutManager" row-count="5" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
|
||||
@@ -32,9 +32,17 @@
|
||||
<text resource-bundle="messages/CodeInsightBundle" key="dialog.reformat.files.optimize.imports.checkbox"/>
|
||||
</properties>
|
||||
</component>
|
||||
<component id="a0a79" class="javax.swing.JCheckBox" binding="myOnlyChangedText">
|
||||
<constraints>
|
||||
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text resource-bundle="messages/CodeInsightBundle" key="reformat.option.vcs.changed.region"/>
|
||||
</properties>
|
||||
</component>
|
||||
<vspacer id="8d758">
|
||||
<constraints>
|
||||
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
<component id="cf942" class="javax.swing.JCheckBox" binding="myRearrangeEntriesCb">
|
||||
|
||||
@@ -29,6 +29,7 @@ public class ReformatFilesDialog extends DialogWrapper implements ReformatFilesO
|
||||
@NotNull private Project myProject;
|
||||
private JPanel myPanel;
|
||||
private JCheckBox myOptimizeImports;
|
||||
private JCheckBox myOnlyChangedText;
|
||||
private JCheckBox myRearrangeEntriesCb;
|
||||
|
||||
public ReformatFilesDialog(@NotNull Project project, @NotNull VirtualFile[] files) {
|
||||
@@ -36,6 +37,11 @@ public class ReformatFilesDialog extends DialogWrapper implements ReformatFilesO
|
||||
myProject = project;
|
||||
setTitle(CodeInsightBundle.message("dialog.reformat.files.title"));
|
||||
myOptimizeImports.setSelected(isOptmizeImportsOptionOn());
|
||||
boolean canTargetVcsChanges = FormatChangedTextUtil.hasChanges(files, project);
|
||||
myOnlyChangedText.setEnabled(canTargetVcsChanges);
|
||||
myOnlyChangedText.setSelected(
|
||||
canTargetVcsChanges && PropertiesComponent.getInstance().getBoolean(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, false)
|
||||
);
|
||||
myOptimizeImports.setSelected(isOptmizeImportsOptionOn());
|
||||
myRearrangeEntriesCb.setSelected(LayoutCodeSettingsStorage.getLastSavedRearrangeEntriesCbStateFor(myProject));
|
||||
init();
|
||||
@@ -53,7 +59,7 @@ public class ReformatFilesDialog extends DialogWrapper implements ReformatFilesO
|
||||
|
||||
@Override
|
||||
public boolean isProcessOnlyChangedText() {
|
||||
return false;
|
||||
return myOnlyChangedText.isEnabled() && myOnlyChangedText.isSelected();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -65,6 +71,7 @@ public class ReformatFilesDialog extends DialogWrapper implements ReformatFilesO
|
||||
protected void doOKAction() {
|
||||
super.doOKAction();
|
||||
PropertiesComponent.getInstance().setValue(LayoutCodeConstants.OPTIMIZE_IMPORTS_KEY, Boolean.toString(myOptimizeImports.isSelected()));
|
||||
PropertiesComponent.getInstance().setValue(LayoutCodeConstants.PROCESS_CHANGED_TEXT_KEY, Boolean.toString(myOnlyChangedText.isSelected()));
|
||||
LayoutCodeSettingsStorage.saveRearrangeEntriesOptionFor(myProject, isRearrangeEntries());
|
||||
}
|
||||
|
||||
|
||||
+19
-1
@@ -33,9 +33,11 @@ import com.intellij.openapi.fileEditor.FileEditorManager;
|
||||
import com.intellij.openapi.fileEditor.TextEditor;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.impl.BackgroundableProcessIndicator;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopup;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.ui.popup.LightweightWindowEvent;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -285,10 +287,21 @@ public class ShowImplementationsAction extends AnAction implements PopupAction {
|
||||
@Override
|
||||
public boolean process(JBPopup popup) {
|
||||
usageView.set(component.showInUsageView());
|
||||
myTaskRef = new WeakReference<BackgroundUpdaterTask>(null);
|
||||
popup.cancel();
|
||||
return false;
|
||||
}
|
||||
})
|
||||
.setCancelCallback(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
final BackgroundUpdaterTask task = myTaskRef.get();
|
||||
if (task != null) {
|
||||
task.setCanceled();
|
||||
}
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
})
|
||||
.createPopup();
|
||||
|
||||
updateInBackground(editor, element, component, title, (AbstractPopup)popup, usageView);
|
||||
@@ -315,7 +328,12 @@ public class ShowImplementationsAction extends AnAction implements PopupAction {
|
||||
task.init(popup, component, usageView);
|
||||
|
||||
myTaskRef = new WeakReference<BackgroundUpdaterTask>(task);
|
||||
ProgressManager.getInstance().run(task);
|
||||
ProgressManager.getInstance().runProcessWithProgressAsynchronously(task, new BackgroundableProcessIndicator(task) {
|
||||
@Override
|
||||
public boolean isCanceled() {
|
||||
return super.isCanceled() || task.isCanceled();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected boolean isIncludeAlwaysSelf() {
|
||||
|
||||
+4
-6
@@ -73,12 +73,6 @@ public abstract class BackgroundUpdaterTask<T> extends Task.Backgroundable {
|
||||
myComponent = component;
|
||||
myUsageView = usageView;
|
||||
|
||||
myPopup.addPopupListener(new JBPopupAdapter() {
|
||||
@Override
|
||||
public void onClosed(LightweightWindowEvent event) {
|
||||
setCanceled();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public abstract String getCaption(int size);
|
||||
@@ -91,6 +85,10 @@ public abstract class BackgroundUpdaterTask<T> extends Task.Backgroundable {
|
||||
return canceled;
|
||||
}
|
||||
|
||||
public boolean isCanceled() {
|
||||
return myCanceled;
|
||||
}
|
||||
|
||||
public boolean updateComponent(final PsiElement element, @Nullable final Comparator comparator) {
|
||||
final UsageView view = myUsageView.get();
|
||||
if (view != null && !((UsageViewImpl)view).isDisposed()) {
|
||||
|
||||
@@ -152,10 +152,8 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
private Component myContextComponent;
|
||||
private CalcThread myCalcThread;
|
||||
private static AtomicBoolean ourShiftIsPressed = new AtomicBoolean(false);
|
||||
private static AtomicBoolean shift1Pressed = new AtomicBoolean(false);
|
||||
private static AtomicBoolean shift1Released = new AtomicBoolean(false);
|
||||
private static AtomicBoolean shift2Pressed = new AtomicBoolean(false);
|
||||
private static AtomicBoolean shift2Released = new AtomicBoolean(false);
|
||||
private final static Couple<AtomicBoolean> ourPressed = Couple.newOne(new AtomicBoolean(false), new AtomicBoolean(false));
|
||||
private final static Couple<AtomicBoolean> ourReleased = Couple.newOne(new AtomicBoolean(false), new AtomicBoolean(false));
|
||||
private static AtomicBoolean ourOtherKeyWasPressed = new AtomicBoolean(false);
|
||||
private static AtomicLong ourLastTimePressed = new AtomicLong(0);
|
||||
private static AtomicBoolean showAll = new AtomicBoolean(false);
|
||||
@@ -185,7 +183,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
return false;
|
||||
}
|
||||
ourOtherKeyWasPressed.set(false);
|
||||
if (shift1Pressed.get() && System.currentTimeMillis() - ourLastTimePressed.get() > 500) {
|
||||
if (ourPressed.first.get() && System.currentTimeMillis() - ourLastTimePressed.get() > 500) {
|
||||
resetState();
|
||||
}
|
||||
handleShift((KeyEvent)event);
|
||||
@@ -203,37 +201,37 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
}
|
||||
|
||||
private void resetState() {
|
||||
shift1Pressed.set(false);
|
||||
shift1Released.set(false);
|
||||
shift2Pressed.set(false);
|
||||
shift2Released.set(false);
|
||||
ourPressed.first.set(false);
|
||||
ourPressed.second.set(false);
|
||||
ourReleased.first.set(false);
|
||||
ourReleased.second.set(false);
|
||||
}
|
||||
|
||||
private void handleShift(KeyEvent event) {
|
||||
if (shift1Pressed.get() && System.currentTimeMillis() - ourLastTimePressed.get() > 300) {
|
||||
if (ourPressed.first.get() && System.currentTimeMillis() - ourLastTimePressed.get() > 300) {
|
||||
resetState();
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getID() == KeyEvent.KEY_PRESSED) {
|
||||
if (!shift1Pressed.get()) {
|
||||
if (!ourPressed.first.get()) {
|
||||
resetState();
|
||||
shift1Pressed.set(true);
|
||||
ourPressed.first.set(true);
|
||||
ourLastTimePressed.set(System.currentTimeMillis());
|
||||
return;
|
||||
} else {
|
||||
if (shift1Pressed.get() && shift1Released.get()) {
|
||||
shift2Pressed.set(true);
|
||||
if (ourPressed.first.get() && ourReleased.first.get()) {
|
||||
ourPressed.second.set(true);
|
||||
ourLastTimePressed.set(System.currentTimeMillis());
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (event.getID() == KeyEvent.KEY_RELEASED) {
|
||||
if (shift1Pressed.get() && !shift1Released.get()) {
|
||||
shift1Released.set(true);
|
||||
if (ourPressed.first.get() && !ourReleased.first.get()) {
|
||||
ourReleased.first.set(true);
|
||||
ourLastTimePressed.set(System.currentTimeMillis());
|
||||
return;
|
||||
} else if (shift1Pressed.get() && shift1Released.get() && shift2Pressed.get()) {
|
||||
} else if (ourPressed.first.get() && ourReleased.first.get() && ourPressed.second.get()) {
|
||||
resetState();
|
||||
run(event);
|
||||
return;
|
||||
@@ -426,16 +424,9 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
@Override
|
||||
protected void textChanged(DocumentEvent e) {
|
||||
final String pattern = editor.getText();
|
||||
final int len = pattern.trim().length();
|
||||
myAlarm.cancelAllRequests();
|
||||
myAlarm.addRequest(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (editor.hasFocus()) {
|
||||
rebuildList(pattern);
|
||||
}
|
||||
}
|
||||
}, len == 1 ? 400 : len == 2 ? 300 : len == 3 ? 250 : 30);
|
||||
if (editor.hasFocus()) {
|
||||
rebuildList(pattern);
|
||||
}
|
||||
}
|
||||
});
|
||||
editor.addFocusListener(new FocusAdapter() {
|
||||
@@ -1021,7 +1012,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
final int width = myMainPanel.getPreferredSize().width;
|
||||
if (width > myPopupActualWidth) {
|
||||
myPopupActualWidth = width;
|
||||
schedulePopupUpdate();
|
||||
//schedulePopupUpdate();
|
||||
}
|
||||
return myMainPanel;
|
||||
}
|
||||
|
||||
@@ -45,6 +45,15 @@ public class LazyRangeMarkerFactory {
|
||||
EditorFactory.getInstance().getEventMulticaster().addDocumentListener(new DocumentAdapter() {
|
||||
@Override
|
||||
public void beforeDocumentChange(DocumentEvent e) {
|
||||
transformRangeMarkers(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void documentChanged(DocumentEvent e) {
|
||||
transformRangeMarkers(e);
|
||||
}
|
||||
|
||||
private void transformRangeMarkers(DocumentEvent e) {
|
||||
VirtualFile file = fileDocumentManager.getFile(e.getDocument());
|
||||
if (file == null) {
|
||||
return;
|
||||
@@ -58,8 +67,7 @@ public class LazyRangeMarkerFactory {
|
||||
List<LazyMarker> markers = lazyMarkers.toStrongList();
|
||||
List<LazyMarker> markersToRemove = null;
|
||||
for (LazyMarker marker : markers) {
|
||||
if (file.equals(marker.getFile())) {
|
||||
marker.getOrCreateDelegate();
|
||||
if (file.equals(marker.getFile()) && marker.documentChanged(e.getDocument()) != null) {
|
||||
if (markersToRemove == null) {
|
||||
markersToRemove = new SmartList<LazyMarker>();
|
||||
}
|
||||
@@ -143,13 +151,26 @@ public class LazyRangeMarkerFactory {
|
||||
return myDelegate;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nullable
|
||||
protected final RangeMarker documentChanged(@NotNull Document document) {
|
||||
if (myDelegate == null) {
|
||||
myDelegate = createDelegate(myFile, document);
|
||||
}
|
||||
return myDelegate;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected abstract RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull Document document);
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Document getDocument() {
|
||||
return getOrCreateDelegate().getDocument();
|
||||
RangeMarker delegate = getOrCreateDelegate();
|
||||
if (delegate == null) {
|
||||
//noinspection ConstantConditions
|
||||
return FileDocumentManager.getInstance().getDocument(myFile);
|
||||
}
|
||||
return delegate.getDocument();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -222,10 +243,13 @@ public class LazyRangeMarkerFactory {
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull final Document document) {
|
||||
int offset = calculateOffset(myProject, file, document, myLine, myColumn);
|
||||
@Nullable
|
||||
public RangeMarker createDelegate(@NotNull VirtualFile file, @NotNull Document document) {
|
||||
if (document.getTextLength() == 0 && !(myLine == 0 && myColumn == 0)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int offset = calculateOffset(myProject, file, document, myLine, myColumn);
|
||||
return document.createRangeMarker(offset, offset);
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ import javax.xml.parsers.SAXParserFactory;
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
@@ -329,6 +330,9 @@ public abstract class PluginManagerMain implements Disposable {
|
||||
}
|
||||
catch (ProcessCanceledException ignore) {
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
LOG.info(e);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.info(e);
|
||||
errorMessages.add(e.getMessage());
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.ide.startupWizardV2;
|
||||
|
||||
import com.intellij.CommonBundle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class FeaturedPluginsPage extends AbstractWizardPage{
|
||||
@NotNull
|
||||
@Override
|
||||
String getID() {
|
||||
return "Featured plugins";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
String getTitle() {
|
||||
return "Download featured plugins";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
String getHeader() {
|
||||
return "We have a few plugins in our web repository that most users like to download. Perhaps, you need them too?";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
String getFooter() {
|
||||
return "New plugins can be also downloaded in " + CommonBundle.settingsTitle() +" | Plugins";
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.ide.startupWizardV2;
|
||||
|
||||
import com.intellij.CommonBundle;
|
||||
import com.intellij.ide.ui.laf.IntelliJLookAndFeelInfo;
|
||||
import com.intellij.ide.ui.laf.darcula.DarculaLookAndFeelInfo;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.util.IconUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class LafPage extends AbstractWizardPage {
|
||||
private static final String AQUA = "Default";
|
||||
private static final String DARCULA = "Darcula";
|
||||
private static final String ALLOY = "Alloy. IDEA Theme";
|
||||
private static final String INTELLIJ = "IntelliJ";
|
||||
private static final String GTK = "GTK+";
|
||||
|
||||
private Map<UIManager.LookAndFeelInfo, Icon> myLafs = new LinkedHashMap<UIManager.LookAndFeelInfo, Icon>();
|
||||
private final JLabel myPreviewLabel = new JLabel();
|
||||
private final boolean myVertical;
|
||||
|
||||
public LafPage() {
|
||||
boolean isAlloyAvailable = false;
|
||||
boolean isGTKAvailable = false;
|
||||
for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
|
||||
if (ALLOY.equals(info.getName())) {
|
||||
isAlloyAvailable = true;
|
||||
}
|
||||
if (GTK.equals(info.getName())) {
|
||||
isGTKAvailable = true;
|
||||
}
|
||||
}
|
||||
final String osPrefix = SystemInfo.isMac ? "OSX" : SystemInfo.isWindows ? "Windows" : "Linux";
|
||||
|
||||
if (SystemInfo.isMac) {
|
||||
myLafs.put(new UIManager.LookAndFeelInfo(AQUA, "com.apple.laf.AquaLookAndFeel"), IconLoader.getIcon("/lafs/OSXAqua.png"));
|
||||
}
|
||||
else {
|
||||
if (isAlloyAvailable) {
|
||||
myLafs.put(new UIManager.LookAndFeelInfo(ALLOY, "com.incors.plaf.alloy.AlloyIdea"),
|
||||
IconLoader.getIcon("/lafs/" + osPrefix + "Alloy.png"));
|
||||
}
|
||||
else {
|
||||
myLafs.put(new IntelliJLookAndFeelInfo(), IconLoader.getIcon("/lafs/" + osPrefix + "IntelliJ.png"));
|
||||
}
|
||||
}
|
||||
|
||||
myLafs.put(new DarculaLookAndFeelInfo(), IconLoader.getIcon("/lafs/" + osPrefix + "Darcula.png"));
|
||||
|
||||
if (SystemInfo.isLinux && isGTKAvailable) {
|
||||
myLafs.put(new UIManager.LookAndFeelInfo(GTK, "com.sun.java.swing.plaf.gtk.GTKLookAndFeel"),
|
||||
IconLoader.getIcon("/lafs/" + osPrefix + "GTK.png"));
|
||||
}
|
||||
|
||||
myVertical = myLafs.size() > 2;
|
||||
JPanel buttonPanel = new JPanel(myVertical ? new GridLayout(myLafs.size(), 1, 5, 5) : new GridLayout(1, myLafs.size(), 5, 5));
|
||||
ButtonGroup group = new ButtonGroup();
|
||||
boolean isFirst = true;
|
||||
for (Map.Entry<UIManager.LookAndFeelInfo, Icon> entry : myLafs.entrySet()) {
|
||||
JPanel p = new JPanel(new BorderLayout());
|
||||
JRadioButton radioButton = new JRadioButton(entry.getKey().getName(), isFirst);
|
||||
isFirst = false;
|
||||
group.add(radioButton);
|
||||
p.add(radioButton, BorderLayout.NORTH);
|
||||
Icon icon = entry.getValue();
|
||||
buttonPanel.add(new JLabel(myVertical ?
|
||||
new ImageIcon(IconUtil.toImage(icon)
|
||||
.getScaledInstance(icon.getIconWidth() / 3, icon.getIconHeight() / 3, Image.SCALE_AREA_AVERAGING))
|
||||
: icon));
|
||||
}
|
||||
setLayout(new BorderLayout());
|
||||
add(buttonPanel, BorderLayout.CENTER);
|
||||
if (myVertical) {
|
||||
add(myPreviewLabel, BorderLayout.EAST);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
String getTitle() {
|
||||
return "Set UI Theme";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
String getID() {
|
||||
return "UI Themes";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
String getFooter() {
|
||||
return "UI theme can be changed later in " + CommonBundle.settingsTitle() + " | Appearance.";
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.ide.startupWizardV2;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationNamesInfo;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PluginsPage extends AbstractWizardPage {
|
||||
@NotNull
|
||||
@Override
|
||||
String getID() {
|
||||
return "Default plugins";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
String getTitle() {
|
||||
return "Tune " + ApplicationNamesInfo.getInstance().getProductName() + " to your tasks";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
String getHeader() {
|
||||
return ApplicationNamesInfo.getInstance().getProductName() + " has a lot of tools enabled by default. You can set only the ones you need or leave them all.";
|
||||
}
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.ide.startupWizardV2;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationNamesInfo;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.VerticalFlowLayout;
|
||||
import com.intellij.openapi.util.IconLoader;
|
||||
import com.intellij.ui.JBCardLayout;
|
||||
import com.intellij.ui.components.JBScrollPane;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import java.awt.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class StartupWizard2 extends DialogWrapper implements ActionListener {
|
||||
|
||||
private final JLabel myNavLabel = new JLabel();
|
||||
private final JLabel myHeaderLabel = new JLabel();
|
||||
private final JLabel myFooterLabel = new JLabel();
|
||||
private final JBCardLayout myCardLayout = new JBCardLayout();
|
||||
private final JPanel myContentPanel = new JPanel(myCardLayout);
|
||||
|
||||
private final JButton mySkipButton = new JButton();
|
||||
private final JButton myBackwardButton = new JButton();
|
||||
private final JButton myForwardButton = new JButton();
|
||||
|
||||
private List<AbstractWizardPage> myPages = Arrays.asList(new LafPage(), new KeymapPage(), new PluginsPage(), new FeaturedPluginsPage());
|
||||
private int myIndex = -1;
|
||||
|
||||
public StartupWizard2() {
|
||||
super(null, true, true);
|
||||
IconLoader.activate();
|
||||
getPeer().setAppIcons();
|
||||
setResizable(false);
|
||||
setTitle("Customize" + ApplicationNamesInfo.getInstance().getProductName());
|
||||
init();
|
||||
showPage(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dispose() {
|
||||
super.dispose();
|
||||
IconLoader.deactivate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
return new Dimension(700, 700);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
if (event.getSource() == mySkipButton) {
|
||||
doOKAction();
|
||||
}
|
||||
if (event.getSource() == myBackwardButton) {
|
||||
showPage(myIndex - 1);
|
||||
}
|
||||
if (event.getSource() == myForwardButton) {
|
||||
if (myIndex == myPages.size() - 1) {
|
||||
doOKAction();
|
||||
}
|
||||
else {
|
||||
showPage(myIndex + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void showPage(int index) {
|
||||
myIndex = index;
|
||||
AbstractWizardPage page = myPages.get(index);
|
||||
myCardLayout.swipe(myContentPanel, page.getID(), JBCardLayout.SwipeDirection.AUTO);
|
||||
updateNavLabel();
|
||||
myHeaderLabel.setText("<html><body><h2>" + page.getTitle() + "</h2>" + page.getHeader() + "</body></html>");
|
||||
myFooterLabel.setText("<html><body>" + page.getFooter() + "</body></html>");
|
||||
mySkipButton.setText(myIndex>0?"Skip All and Set Defaults" : "Skip Remaining and Set Defaults");
|
||||
myBackwardButton.setVisible(myIndex>0);
|
||||
if (myIndex > 0) {
|
||||
myBackwardButton.setText("Back to " + myPages.get(myIndex-1).getID());
|
||||
}
|
||||
myForwardButton.setText(myIndex < myPages.size() - 1 ? "Next: " + myPages.get(myIndex+1).getID() : "Start using " + ApplicationNamesInfo
|
||||
.getInstance().getFullProductName());
|
||||
}
|
||||
|
||||
private void updateNavLabel() {
|
||||
StringBuilder sb = new StringBuilder("<html><body>");
|
||||
for (int i = 0; i < myPages.size(); i++) {
|
||||
AbstractWizardPage wizardPage = myPages.get(i);
|
||||
if (i > 0 && i < myPages.size() - 1) sb.append(" → ");
|
||||
if (i == myIndex) sb.append("<b>");
|
||||
sb.append(wizardPage.getID());
|
||||
if (i == myIndex) sb.append("</b>");
|
||||
}
|
||||
sb.append("</body></html>");
|
||||
myNavLabel.setText(sb.toString());
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected JComponent createCenterPanel() {
|
||||
for (AbstractWizardPage page : myPages) {
|
||||
myContentPanel.add(page, page.getID());
|
||||
}
|
||||
JPanel mainPanel = new JPanel(new VerticalFlowLayout());
|
||||
mainPanel.add(myNavLabel);
|
||||
mainPanel.add(myHeaderLabel);
|
||||
mainPanel.add(
|
||||
new JBScrollPane(myContentPanel, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER));
|
||||
mainPanel.add(myFooterLabel);
|
||||
return mainPanel;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected JComponent createSouthPanel() {
|
||||
JPanel result = new JPanel(new GridBagLayout());
|
||||
result.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||
GridBagConstraints gbc = new GridBagConstraints();
|
||||
gbc.gridy = 0;
|
||||
result.add(mySkipButton, gbc);
|
||||
result.add(myBackwardButton, gbc);
|
||||
gbc.weightx = 1;
|
||||
result.add(Box.createHorizontalGlue(), gbc);
|
||||
gbc.weightx = 0;
|
||||
result.add(myForwardButton, gbc);
|
||||
|
||||
mySkipButton.addActionListener(this);
|
||||
myBackwardButton.addActionListener(this);
|
||||
myForwardButton.addActionListener(this);
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+1
-14
@@ -18,7 +18,6 @@ package com.intellij.openapi.vfs.impl.jar;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ModalityState;
|
||||
import com.intellij.openapi.application.PathManager;
|
||||
import com.intellij.openapi.components.ApplicationComponent;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileAttributes;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
@@ -44,7 +43,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class JarFileSystemImpl extends JarFileSystem implements ApplicationComponent {
|
||||
public class JarFileSystemImpl extends JarFileSystem {
|
||||
private static final class JarFileSystemImplLock { }
|
||||
private static final JarFileSystemImplLock LOCK = new JarFileSystemImplLock();
|
||||
|
||||
@@ -125,18 +124,6 @@ public class JarFileSystemImpl extends JarFileSystem implements ApplicationCompo
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getComponentName() {
|
||||
return "JarFileSystem";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initComponent() { }
|
||||
|
||||
@Override
|
||||
public void disposeComponent() { }
|
||||
|
||||
@Override
|
||||
public void setNoCopyJarForPath(String pathInJar) {
|
||||
if (myNoCopyJarPaths == null || pathInJar == null) return;
|
||||
|
||||
+8
-3
@@ -3,11 +3,16 @@ package com.intellij.util.io.socketConnection;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public enum ConnectionStatus {
|
||||
NOT_CONNECTED("Not connected"), WAITING_FOR_CONNECTION("Waiting for connection"), CONNECTED("Connected"), DISCONNECTED("Disconnected"),
|
||||
CONNECTION_FAILED("Connection failed");
|
||||
NOT_CONNECTED("Not connected"),
|
||||
WAITING_FOR_CONNECTION("Waiting for connection"),
|
||||
CONNECTED("Connected"),
|
||||
DISCONNECTED("Disconnected"),
|
||||
CONNECTION_FAILED("Connection failed"),
|
||||
DETACHED("Detached");
|
||||
|
||||
private final String myStatusText;
|
||||
|
||||
ConnectionStatus(String statusText) {
|
||||
ConnectionStatus(@NotNull String statusText) {
|
||||
myStatusText = statusText;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ home.directory.not.specified.for.jdk.error.message=Home directory is not specifi
|
||||
run.configuration.pause.output.action.name=Pause Output
|
||||
main.class.is.not.specified.error.message=Main class is not specified
|
||||
close.tab.action.name=Close
|
||||
run.configuration.show.command.line.action.name=Show command line
|
||||
run.configuration.show.command.line.action.name=Show Python Prompt
|
||||
|
||||
#---
|
||||
create.run.configuration.action.name=Create Run Configuration
|
||||
|
||||
+16
-14
@@ -13,27 +13,29 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.ide.startupWizardV2;
|
||||
package com.intellij.codeInsight.actions;
|
||||
|
||||
import com.intellij.CommonBundle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
public class ChangedLines {
|
||||
public final int from;
|
||||
public final int to;
|
||||
|
||||
public class KeymapPage extends AbstractWizardPage {
|
||||
@NotNull
|
||||
@Override
|
||||
String getID() {
|
||||
return "Keymaps";
|
||||
ChangedLines(int from, int to) {
|
||||
this.from = from;
|
||||
this.to = to;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
String getTitle() {
|
||||
return "Select keymap scheme";
|
||||
public String toString() {
|
||||
return "(" + from + ", " + to + ")";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
String getFooter() {
|
||||
return "Keymap scheme can be later changed in " + CommonBundle.settingsTitle() + " | Keymap";
|
||||
public boolean equals(Object obj) {
|
||||
if (obj instanceof ChangedLines) {
|
||||
ChangedLines line = (ChangedLines)obj;
|
||||
return from == line.from && to == line.to;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.codeInsight.actions;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.Indent;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.ThrowableRunnable;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
public class MockCodeStyleManager extends CodeStyleManager {
|
||||
private Map<PsiFile, ChangedLines[]> myFormattedLinesForFile = new HashMap<PsiFile, ChangedLines[]>();
|
||||
|
||||
@NotNull
|
||||
public ChangedLines[] getFormattedLinesFor(@NotNull PsiFile file) {
|
||||
ChangedLines[] changedLines = myFormattedLinesForFile.get(file);
|
||||
return changedLines != null ? changedLines : new ChangedLines[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reformatText(@NotNull PsiFile file, @NotNull Collection<TextRange> ranges) throws IncorrectOperationException {
|
||||
Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file);
|
||||
assert(document != null);
|
||||
|
||||
ChangedLines[] formattedLines = new ChangedLines[ranges.size()];
|
||||
int i = 0;
|
||||
for (TextRange range : ranges) {
|
||||
int lineStart = document.getLineNumber(range.getStartOffset());
|
||||
int lineEnd = document.getLineNumber(range.getEndOffset());
|
||||
formattedLines[i++] = new ChangedLines(lineStart, lineEnd);
|
||||
}
|
||||
|
||||
myFormattedLinesForFile.put(file, formattedLines);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Project getProject() {
|
||||
throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.getProject(...)");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement reformat(@NotNull PsiElement element) throws IncorrectOperationException {
|
||||
throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.reformat(...)");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElement reformat(@NotNull PsiElement element, boolean canChangeWhiteSpacesOnly) throws IncorrectOperationException {
|
||||
throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.reformat(...)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement reformatRange(@NotNull PsiElement element, int startOffset, int endOffset) throws IncorrectOperationException {
|
||||
throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.reformatRange(...)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiElement reformatRange(@NotNull PsiElement element, int startOffset, int endOffset, boolean canChangeWhiteSpacesOnly)
|
||||
throws IncorrectOperationException {
|
||||
throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.reformatRange(...)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reformatText(@NotNull PsiFile file, int startOffset, int endOffset) throws IncorrectOperationException {
|
||||
throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.reformatText(...)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void adjustLineIndent(@NotNull PsiFile file, TextRange rangeToAdjust) throws IncorrectOperationException {
|
||||
throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.adjustLineIndent(...)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int adjustLineIndent(@NotNull PsiFile file, int offset) throws IncorrectOperationException {
|
||||
throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.adjustLineIndent(...)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int adjustLineIndent(@NotNull Document document, int offset) {
|
||||
throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.adjustLineIndent(...)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLineToBeIndented(@NotNull PsiFile file, int offset) {
|
||||
throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.isLineToBeIndented(...)");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getLineIndent(@NotNull PsiFile file, int offset) {
|
||||
throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.getLineIndent(...)");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getLineIndent(@NotNull Document document, int offset) {
|
||||
throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.getLineIndent(...)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Indent getIndent(String text, FileType fileType) {
|
||||
throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.getIndent(...)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String fillIndent(Indent indent, FileType fileType) {
|
||||
throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.fillIndent(...)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Indent zeroIndent() {
|
||||
throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.zeroIndent(...)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reformatNewlyAddedElement(@NotNull ASTNode block, @NotNull ASTNode addedElement)
|
||||
throws IncorrectOperationException {
|
||||
throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.reformatNewlyAddedElement(...)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSequentialProcessingAllowed() {
|
||||
throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockCodeStyleManager.isSequentialProcessingAllowed(...)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void performActionWithFormatterDisabled(Runnable r) {
|
||||
throw new UnsupportedOperationException(
|
||||
"com.intellij.codeInsight.actions.MockCodeStyleManager.performActionWithFormatterDisabled(...)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Throwable> void performActionWithFormatterDisabled(ThrowableRunnable<T> r) throws T {
|
||||
throw new UnsupportedOperationException(
|
||||
"com.intellij.codeInsight.actions.MockCodeStyleManager.performActionWithFormatterDisabled(...)");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T performActionWithFormatterDisabled(Computable<T> r) {
|
||||
throw new UnsupportedOperationException(
|
||||
"com.intellij.codeInsight.actions.MockCodeStyleManager.performActionWithFormatterDisabled(...)");
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.codeInsight.actions;
|
||||
|
||||
import com.intellij.formatting.CustomFormattingModelBuilder;
|
||||
import com.intellij.formatting.FormattingModel;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class MockPlainTextFormattingModelBuilder implements CustomFormattingModelBuilder {
|
||||
|
||||
@Override
|
||||
public boolean isEngagedToFormat(PsiElement context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public FormattingModel createModel(PsiElement element, CodeStyleSettings settings) {
|
||||
throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockPlainTextFormattingModelBuilder.createModel(...)");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public TextRange getRangeAffectingIndent(PsiFile file, int offset, ASTNode elementAtOffset) {
|
||||
throw new UnsupportedOperationException("com.intellij.codeInsight.actions.MockPlainTextFormattingModelBuilder.getRangeAffectingIndent(...)");
|
||||
}
|
||||
}
|
||||
+339
@@ -0,0 +1,339 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.codeInsight.actions;
|
||||
|
||||
import com.intellij.lang.LanguageFormatting;
|
||||
import com.intellij.openapi.components.impl.ComponentManagerImpl;
|
||||
import com.intellij.openapi.fileTypes.PlainTextLanguage;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.FilePathImpl;
|
||||
import com.intellij.openapi.vcs.changes.Change;
|
||||
import com.intellij.openapi.vcs.changes.ChangeListManager;
|
||||
import com.intellij.openapi.vcs.changes.ContentRevision;
|
||||
import com.intellij.openapi.vcs.changes.SimpleContentRevision;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.testFramework.LightPlatformTestCase;
|
||||
import com.intellij.testFramework.PlatformTestCase;
|
||||
import com.intellij.testFramework.vcs.MockChangeListManager;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.picocontainer.MutablePicoContainer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
public class ReformatOnlyVcsChangedTextTest extends LightPlatformTestCase {
|
||||
private static final String TEMP_DIR_NAME = "dir";
|
||||
private PsiDirectory myWorkingDirectory;
|
||||
|
||||
private MockChangeListManager myMockChangeListManager;
|
||||
private MockCodeStyleManager myMockCodeStyleManager;
|
||||
private MockPlainTextFormattingModelBuilder myMockPlainTextFormattingModelBuilder;
|
||||
|
||||
private ChangeListManager myRealChangeListManager;
|
||||
private CodeStyleManager myRealCodeStyleManger;
|
||||
|
||||
private final static String COMMITTED =
|
||||
"class Test {\n" +
|
||||
" int a = 22;\n" +
|
||||
" public String getName() { return \"Test\"; }\n" +
|
||||
"}";
|
||||
|
||||
private final static String MODIFIED =
|
||||
"class Test {\n" +
|
||||
" int a = 22;\n" +
|
||||
" long l;\n" +
|
||||
" double d;\n" +
|
||||
" int i;\n" +
|
||||
" public String getName() { return \"Test\"; }\n" +
|
||||
" String test1;\n" +
|
||||
" String test2;\n" +
|
||||
"}";
|
||||
|
||||
private final static ChangedLines[] CHANGED_LINES = new ChangedLines[] { line(2, 4), line(6, 7) };
|
||||
private final static ChangedLines[] NO_CHANGED_LINES = new ChangedLines[0];
|
||||
|
||||
@Override
|
||||
public void setUp() throws Exception {
|
||||
PlatformTestCase.initPlatformLangPrefix();
|
||||
super.setUp();
|
||||
myWorkingDirectory = TestFileStructure.createDirectory(getProject(), getSourceRoot(), TEMP_DIR_NAME);
|
||||
|
||||
myRealChangeListManager = ChangeListManager.getInstance(getProject());
|
||||
myMockChangeListManager = new MockChangeListManager();
|
||||
registerChangeListManager(myMockChangeListManager);
|
||||
|
||||
myRealCodeStyleManger = CodeStyleManager.getInstance(getProject());
|
||||
myMockCodeStyleManager = new MockCodeStyleManager();
|
||||
registerCodeStyleManager(myMockCodeStyleManager);
|
||||
|
||||
myMockPlainTextFormattingModelBuilder = new MockPlainTextFormattingModelBuilder();
|
||||
LanguageFormatting.INSTANCE.addExplicitExtension(PlainTextLanguage.INSTANCE, myMockPlainTextFormattingModelBuilder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
registerChangeListManager(myRealChangeListManager);
|
||||
registerCodeStyleManager(myRealCodeStyleManger);
|
||||
LanguageFormatting.INSTANCE.removeExplicitExtension(PlainTextLanguage.INSTANCE, myMockPlainTextFormattingModelBuilder);
|
||||
|
||||
TestFileStructure.delete(myWorkingDirectory.getVirtualFile());
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
public void testInsertion() throws IOException {
|
||||
doTest(
|
||||
"public class B {\n" +
|
||||
" int a = 3;\n" +
|
||||
" String text;\n" +
|
||||
" Object last = null;\n" +
|
||||
"}",
|
||||
|
||||
"public class B {\n" +
|
||||
" int a = 3;\n" +
|
||||
" int toIndent1 = 1;\n" +
|
||||
" String text;\n" +
|
||||
" int toIndent2\n" +
|
||||
" Object last = null;\n" +
|
||||
"}",
|
||||
|
||||
line(2, 2), line(4, 4)
|
||||
);
|
||||
}
|
||||
|
||||
private static ChangedLines line(int from, int to) {
|
||||
return new ChangedLines(from, to);
|
||||
}
|
||||
|
||||
public void testDeletion() throws IOException {
|
||||
doTest(
|
||||
"public class B {\n" +
|
||||
" int a = 3;\n" +
|
||||
" String text;\n" +
|
||||
" Object last = null;\n" +
|
||||
" Object first = null;\n" +
|
||||
" Object second = null;\n" +
|
||||
"}",
|
||||
|
||||
"public class B {\n" +
|
||||
" int newInt = 1;\n" +
|
||||
" Object last = null;\n" +
|
||||
"}",
|
||||
|
||||
line(1, 1)
|
||||
);
|
||||
}
|
||||
|
||||
public void testModification() throws IOException {
|
||||
doTest(
|
||||
"public class B {\n" +
|
||||
" int a = 3;\n" +
|
||||
" String text;\n" +
|
||||
" Object last = null;\n" +
|
||||
" Object first = null;\n" +
|
||||
" Object second = null;\n" +
|
||||
"}",
|
||||
|
||||
"public class B {\n" +
|
||||
" int a = 33;\n" +
|
||||
" String text;\n" +
|
||||
" Object last = new Object();\n" +
|
||||
" Object first = null;\n" +
|
||||
" Object second = new Object();\n" +
|
||||
"}",
|
||||
|
||||
line(1, 1), line(3,3), line(5,5)
|
||||
);
|
||||
}
|
||||
|
||||
public void testReformatFiles() throws IOException {
|
||||
ChangedFilesStructure fs = new ChangedFilesStructure(myWorkingDirectory);
|
||||
|
||||
PsiFile m1 = fs.createFile("Test1.java", COMMITTED, MODIFIED);
|
||||
PsiFile u1 = fs.createFile("Test2.java", COMMITTED, COMMITTED);
|
||||
|
||||
fs.createDirectoryAndMakeItCurrent();
|
||||
PsiFile m2 = fs.createFile("Test3.java", COMMITTED, MODIFIED);
|
||||
PsiFile u2 = fs.createFile("Test4.java", COMMITTED, COMMITTED);
|
||||
|
||||
new ReformatCodeProcessor(getProject(), new PsiFile[] {m1, m2, u1, u2}, null, true).run();
|
||||
|
||||
assertFormattedLines(CHANGED_LINES, m1, m2);
|
||||
assertFormattedLines(NO_CHANGED_LINES, u1, u2);
|
||||
}
|
||||
|
||||
public void testNoChangesNoFormatting() throws IOException {
|
||||
ChangedFilesStructure fs = new ChangedFilesStructure(myWorkingDirectory);
|
||||
|
||||
PsiFile u1 = fs.createFile("Test1.java", COMMITTED, COMMITTED);
|
||||
PsiFile u2 = fs.createFile("Test2.java", COMMITTED, COMMITTED);
|
||||
|
||||
reformatDirectory(fs.getCurrentDirectory());
|
||||
|
||||
assertFormattedLines(NO_CHANGED_LINES, u1, u2);
|
||||
}
|
||||
|
||||
|
||||
public void testReformatOnlyChanged() throws IOException {
|
||||
ChangedFilesStructure fs = new ChangedFilesStructure(myWorkingDirectory);
|
||||
|
||||
PsiFile untouched1 = fs.createFile("Test1.java", COMMITTED, COMMITTED);
|
||||
PsiFile untouched2 = fs.createFile("Test2.java", COMMITTED, COMMITTED);
|
||||
|
||||
PsiFile modified1 = fs.createFile("Test4.java", COMMITTED, MODIFIED);
|
||||
PsiFile modified2 = fs.createFile("Test5.java", COMMITTED, MODIFIED);
|
||||
PsiFile modified3 = fs.createFile("Test6.java", COMMITTED, MODIFIED);
|
||||
|
||||
reformatDirectory(fs.getCurrentDirectory());
|
||||
|
||||
|
||||
assertFormattedLines(CHANGED_LINES, modified1, modified2, modified3);
|
||||
assertFormattedLines(NO_CHANGED_LINES, untouched1, untouched2);
|
||||
}
|
||||
|
||||
public void testReformatInAllSubtree() throws IOException {
|
||||
ChangedFilesStructure fs = new ChangedFilesStructure(myWorkingDirectory);
|
||||
PsiFile modified11 = fs.createFile("Test4.java", COMMITTED, MODIFIED);
|
||||
PsiFile modified12 = fs.createFile("Test5.java", COMMITTED, MODIFIED);
|
||||
|
||||
fs.createDirectoryAndMakeItCurrent();
|
||||
PsiDirectory dirToReformat = fs.getCurrentDirectory();
|
||||
PsiFile modified21 = fs.createFile("Test6.java", COMMITTED, MODIFIED);
|
||||
PsiFile modified22 = fs.createFile("Test7.java", COMMITTED, MODIFIED);
|
||||
|
||||
fs.createDirectoryAndMakeItCurrent();
|
||||
PsiFile modified31 = fs.createFile("Test8.java", COMMITTED, MODIFIED);
|
||||
PsiFile modified32 = fs.createFile("Test9.java", COMMITTED, MODIFIED);
|
||||
|
||||
reformatDirectory(dirToReformat);
|
||||
|
||||
assertFormattedLines(CHANGED_LINES, modified21, modified22, modified31, modified32);
|
||||
assertFormattedLines(NO_CHANGED_LINES, modified11, modified12);
|
||||
}
|
||||
|
||||
private static void registerChangeListManager(@NotNull ChangeListManager manager) {
|
||||
Project project = getProject();
|
||||
assert (project instanceof ComponentManagerImpl);
|
||||
ComponentManagerImpl projectComponentManager = (ComponentManagerImpl)project;
|
||||
projectComponentManager.registerComponentInstance(ChangeListManager.class, manager);
|
||||
}
|
||||
|
||||
private static void registerCodeStyleManager(@NotNull CodeStyleManager manager) {
|
||||
String componentKey = CodeStyleManager.class.getName();
|
||||
MutablePicoContainer container = (MutablePicoContainer)getProject().getPicoContainer();
|
||||
container.unregisterComponent(componentKey);
|
||||
container.registerComponentInstance(componentKey, manager);
|
||||
}
|
||||
|
||||
private void doTest(@NotNull String committed, @NotNull String modified, @NotNull ChangedLines... lines) throws IOException {
|
||||
ChangedFilesStructure fs = new ChangedFilesStructure(myWorkingDirectory);
|
||||
PsiFile file = fs.createFile("Test.java", committed, modified);
|
||||
reformatDirectory(myWorkingDirectory);
|
||||
assertFormattedRangesEqualsTo(file, lines);
|
||||
}
|
||||
|
||||
private void assertFormattedLines(@NotNull ChangedLines[] expectedLines, @NotNull PsiFile... files) {
|
||||
for (PsiFile file : files)
|
||||
assertFormattedRangesEqualsTo(file, expectedLines);
|
||||
}
|
||||
|
||||
private void assertFormattedRangesEqualsTo(@NotNull PsiFile file, ChangedLines... expected) {
|
||||
ChangedLines[] formatted = myMockCodeStyleManager.getFormattedLinesFor(file);
|
||||
|
||||
Comparator<ChangedLines> cmp = new Comparator<ChangedLines>() {
|
||||
@Override
|
||||
public int compare(ChangedLines o1, ChangedLines o2) {
|
||||
return o1.from < o2.from ? -1 : 1;
|
||||
}
|
||||
};
|
||||
Arrays.sort(expected, cmp);
|
||||
Arrays.sort(formatted, cmp);
|
||||
|
||||
assertTrue(getErrorMessage(expected, formatted), Arrays.equals(expected, formatted));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getErrorMessage(ChangedLines[] expected, ChangedLines[] actual) {
|
||||
return "Expected: " + Arrays.toString(expected) + " Actual: " + Arrays.toString(actual);
|
||||
}
|
||||
|
||||
private static void reformatDirectory(@NotNull PsiDirectory dir) {
|
||||
ReformatCodeProcessor processor = new ReformatCodeProcessor(getProject(), dir, true, true);
|
||||
processor.run();
|
||||
}
|
||||
|
||||
class ChangedFilesStructure {
|
||||
private TestFileStructure myFileStructure;
|
||||
|
||||
public ChangedFilesStructure(@NotNull PsiDirectory directory) {
|
||||
myFileStructure = new TestFileStructure(getModule(), directory);
|
||||
}
|
||||
|
||||
public void createDirectoryAndMakeItCurrent() throws IOException {
|
||||
myFileStructure.createDirectoryAndMakeItCurrent("inner");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiFile createFile(@NotNull String fileName,
|
||||
@NotNull String committedContent,
|
||||
@NotNull String actualContent) throws IOException
|
||||
{
|
||||
PsiFile file = myFileStructure.addTestFile(fileName, actualContent);
|
||||
if (committedContent != actualContent) {
|
||||
registerCommittedRevision(committedContent, file);
|
||||
}
|
||||
return file;
|
||||
}
|
||||
|
||||
private void registerCommittedRevision(@NotNull String committedContent, @NotNull PsiFile... files) {
|
||||
List<Change> changes = createChanges(committedContent, files);
|
||||
injectChanges(changes);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<Change> createChanges(@NotNull String committed, @NotNull PsiFile... files) {
|
||||
List<Change> changes = ContainerUtil.newArrayList();
|
||||
for (PsiFile file : files) {
|
||||
changes.add(createChange(committed, file));
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
|
||||
private void injectChanges(@NotNull List<Change> changes) {
|
||||
Change[] arr = new Change[changes.size()];
|
||||
ContainerUtil.toArray(changes, arr);
|
||||
myMockChangeListManager.addChanges(arr);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Change createChange(@NotNull String committed, @NotNull PsiFile file) {
|
||||
FilePathImpl filePath = new FilePathImpl(file.getVirtualFile());
|
||||
ContentRevision before = new SimpleContentRevision(committed, filePath, "");
|
||||
ContentRevision after = new SimpleContentRevision("", filePath, "");
|
||||
return new Change(before, after);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiDirectory getCurrentDirectory() {
|
||||
return myFileStructure.getCurrentDirectory();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.codeInsight.actions;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.application.WriteAction;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ModuleRootManager;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.impl.file.PsiDirectoryFactory;
|
||||
import com.intellij.testFramework.PsiTestUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TestFileStructure {
|
||||
private int myLevel;
|
||||
@NotNull private Project myProject;
|
||||
@NotNull private Module myModule;
|
||||
@NotNull private PsiDirectory myCurrentLevelDirectory;
|
||||
private List<List<PsiFile>> myFilesForLevel = new ArrayList<List<PsiFile>>();
|
||||
|
||||
public TestFileStructure(@NotNull Module module, @NotNull PsiDirectory root) {
|
||||
myProject = module.getProject();
|
||||
myModule = module;
|
||||
myCurrentLevelDirectory = root;
|
||||
myFilesForLevel.add(new ArrayList<PsiFile>());
|
||||
myLevel = 0;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiFile addTestFile(@NotNull String name, @NotNull String content) throws IOException {
|
||||
PsiFile createdFile = createFile(myModule, myCurrentLevelDirectory.getVirtualFile(), name, content);
|
||||
getCurrentDirectoryFiles().add(createdFile);
|
||||
return createdFile;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<PsiFile> getCurrentDirectoryFiles() {
|
||||
return myFilesForLevel.get(myLevel);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiDirectory getCurrentDirectory() {
|
||||
return myCurrentLevelDirectory;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TestFileStructure createDirectoryAndMakeItCurrent(String name) throws IOException {
|
||||
myLevel++;
|
||||
myFilesForLevel.add(new ArrayList<PsiFile>());
|
||||
myCurrentLevelDirectory = createDirectory(myProject, myCurrentLevelDirectory.getVirtualFile(), name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public List<PsiFile> getFilesAtLevel(int level) {
|
||||
assert (myLevel >= level);
|
||||
return myFilesForLevel.get(level);
|
||||
}
|
||||
|
||||
private PsiFile createFile(final Module module, final VirtualFile vDir, final String fileName, final String text) {
|
||||
return new WriteAction<PsiFile>() {
|
||||
@Override
|
||||
protected void run(@NotNull Result<PsiFile> result) throws Throwable {
|
||||
if (!ModuleRootManager.getInstance(module).getFileIndex().isInSourceContent(vDir)) {
|
||||
PsiTestUtil.addSourceContentToRoots(module, vDir);
|
||||
}
|
||||
|
||||
final VirtualFile vFile = vDir.createChildData(vDir, fileName);
|
||||
VfsUtil.saveText(vFile, text);
|
||||
final PsiFile file = PsiManager.getInstance(myProject).findFile(vFile);
|
||||
assert (file != null);
|
||||
result.setResult(file);
|
||||
}
|
||||
}.execute().getResultObject();
|
||||
}
|
||||
|
||||
public static PsiDirectory createDirectory(@NotNull Project project, @NotNull final VirtualFile parent, @NotNull final String name) throws IOException {
|
||||
final VirtualFile[] dir = new VirtualFile[1];
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
dir[0] = parent.createChildDirectory(null, name);
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
return PsiDirectoryFactory.getInstance(project).createDirectory(dir[0]);
|
||||
}
|
||||
|
||||
public static void delete(@NotNull final VirtualFile file) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
file.delete(null);
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -78,7 +78,7 @@ public abstract class BreakpointBase<L> extends Breakpoint {
|
||||
return this;
|
||||
}
|
||||
enabled = value;
|
||||
dirty = true;
|
||||
dirty = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
package org.jetbrains.debugger;
|
||||
|
||||
import com.intellij.openapi.util.AsyncResult;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.debugger.values.FunctionValue;
|
||||
import org.jetbrains.debugger.values.ObjectValue;
|
||||
import org.jetbrains.debugger.values.Value;
|
||||
|
||||
/**
|
||||
* Exposes additional data if variable is a property of object and its property descriptor
|
||||
@@ -38,10 +34,4 @@ public interface ObjectProperty extends Variable {
|
||||
* @return whether property described as 'enumerable'
|
||||
*/
|
||||
boolean isEnumerable();
|
||||
|
||||
/**
|
||||
* Asynchronously evaluates property getter and returns property value
|
||||
*/
|
||||
@NotNull
|
||||
AsyncResult<Value> evaluateGet(@NotNull ObjectValue host, @NotNull EvaluateContext evaluateContext);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ public final class StandaloneVmHelper extends MessageWriter {
|
||||
|
||||
private final VmEx vm;
|
||||
|
||||
public StandaloneVmHelper(VmEx vm) {
|
||||
public StandaloneVmHelper(@NotNull VmEx vm) {
|
||||
this.vm = vm;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.jetbrains.debugger;
|
||||
|
||||
import com.intellij.openapi.util.ActionCallback;
|
||||
import com.intellij.openapi.util.AsyncResult;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.debugger.values.Value;
|
||||
|
||||
@@ -13,4 +14,7 @@ public interface ValueModifier {
|
||||
ActionCallback setValue(@NotNull Variable variable, String newValue, @NotNull EvaluateContext evaluateContext);
|
||||
|
||||
ActionCallback setValue(@NotNull Variable variable, Value newValue, @NotNull EvaluateContext evaluateContext);
|
||||
|
||||
@NotNull
|
||||
AsyncResult<Value> evaluateGet(@NotNull ObjectProperty property, @NotNull EvaluateContext evaluateContext);
|
||||
}
|
||||
@@ -153,9 +153,9 @@ public final class VariableView extends XNamedValue implements VariableContext {
|
||||
node.setFullValueEvaluator(new XFullValueEvaluator(" (invoke getter)") {
|
||||
@Override
|
||||
public void startEvaluation(@NotNull final XFullValueEvaluationCallback callback) {
|
||||
ObjectValue host = (ObjectValue)((VariableView)context).getValue();
|
||||
assert host != null;
|
||||
ObsolescentAsyncResults.consume(((ObjectProperty)variable).evaluateGet(host, getEvaluateContext()), node, new PairConsumer<Value, XValueNode>() {
|
||||
ValueModifier valueModifier = variable.getValueModifier();
|
||||
assert valueModifier != null;
|
||||
ObsolescentAsyncResults.consume(valueModifier.evaluateGet((ObjectProperty)variable, getEvaluateContext()), node, new PairConsumer<Value, XValueNode>() {
|
||||
@Override
|
||||
public void consume(Value value, XValueNode node) {
|
||||
callback.evaluated("");
|
||||
|
||||
+3
-3
@@ -70,7 +70,7 @@ public abstract class VmConnection<T extends Vm> implements Disposable, BrowserC
|
||||
started.setDone();
|
||||
}
|
||||
|
||||
public final void close(@Nullable String message) {
|
||||
public final void close(@Nullable String message, @NotNull ConnectionStatus status) {
|
||||
if (!closed.compareAndSet(false, true)) {
|
||||
return;
|
||||
}
|
||||
@@ -79,7 +79,7 @@ public abstract class VmConnection<T extends Vm> implements Disposable, BrowserC
|
||||
if (!started.isProcessed()) {
|
||||
started.setRejected();
|
||||
}
|
||||
setState(ConnectionStatus.DISCONNECTED, message);
|
||||
setState(status, message);
|
||||
Disposer.dispose(this, false);
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ public abstract class VmConnection<T extends Vm> implements Disposable, BrowserC
|
||||
vm = null;
|
||||
callback = currentVm.detach();
|
||||
}
|
||||
close(null);
|
||||
close(null, ConnectionStatus.DISCONNECTED);
|
||||
return callback;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -70,7 +70,7 @@ class Generator {
|
||||
}
|
||||
|
||||
private static boolean isDomainSkipped(Domain domain) {
|
||||
if (domain.domain().equals("CSS")) {
|
||||
if (domain.domain().equals("CSS") || domain.domain().equals("Inspector")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+9
-21
@@ -13,29 +13,17 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.ide.startupWizardV2;
|
||||
package com.intellij.openapi.util;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public abstract class AbstractWizardPage extends JPanel {
|
||||
public AbstractWizardPage() {
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public class Couple<T> extends Pair<T, T> {
|
||||
public Couple(T first, T second) {
|
||||
super(first, second);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
abstract String getID();
|
||||
|
||||
@NotNull
|
||||
abstract String getTitle();
|
||||
|
||||
@NotNull
|
||||
String getHeader() {
|
||||
return " ";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
String getFooter() {
|
||||
return " ";
|
||||
public static <T> Couple<T> newOne(T first, T second) {
|
||||
return new Couple<T>(first, second);
|
||||
}
|
||||
}
|
||||
@@ -188,18 +188,7 @@ public class PersistentHashMap<Key, Value> extends PersistentEnumeratorDelegate<
|
||||
}
|
||||
|
||||
private SLRUCache<Key, BufferExposingByteArrayOutputStream> createAppendCache(final KeyDescriptor<Key> keyDescriptor) {
|
||||
final EqualityPolicy<Key> hashingStrategy = new EqualityPolicy<Key>() {
|
||||
@Override
|
||||
public int getHashCode(Key object) {
|
||||
return keyDescriptor.getHashCode(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEqual(Key val1, Key val2) {
|
||||
return keyDescriptor.isEqual(val1, val2);
|
||||
}
|
||||
};
|
||||
return new SLRUCache<Key, BufferExposingByteArrayOutputStream>(16 * 1024, 4 * 1024, hashingStrategy) {
|
||||
return new SLRUCache<Key, BufferExposingByteArrayOutputStream>(16 * 1024, 4 * 1024, keyDescriptor) {
|
||||
@Override
|
||||
@NotNull
|
||||
public BufferExposingByteArrayOutputStream createValue(final Key key) {
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.util.NotNullFunction;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.hash.LinkedHashMap;
|
||||
import com.intellij.vcs.log.Hash;
|
||||
import com.intellij.vcs.log.VcsLogRefManager;
|
||||
import com.intellij.vcs.log.VcsRef;
|
||||
@@ -39,6 +40,14 @@ public class GraphColorManagerImpl implements GraphColorManager {
|
||||
@NotNull private final NotNullFunction<Integer, Hash> myHashGetter;
|
||||
@NotNull private final Map<VirtualFile, VcsLogRefManager> myRefManagers;
|
||||
|
||||
@NotNull private final LinkedHashMap<Integer, Integer> myErrorWasReported = new LinkedHashMap<Integer, Integer>(10) {
|
||||
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<Integer, Integer> eldest) {
|
||||
return size() > 100;
|
||||
}
|
||||
};
|
||||
|
||||
public GraphColorManagerImpl(@NotNull RefsModel refsModel, @NotNull NotNullFunction<Integer, Hash> hashGetter,
|
||||
@NotNull Map<VirtualFile, VcsLogRefManager> refManagers) {
|
||||
myRefsModel = refsModel;
|
||||
@@ -61,7 +70,10 @@ public class GraphColorManagerImpl implements GraphColorManager {
|
||||
|
||||
private boolean checkEmptiness(@NotNull Collection<VcsRef> refs, int head) {
|
||||
if (refs.isEmpty()) {
|
||||
LOG.error("No references found at head " + head + " which corresponds to hash " + myHashGetter.fun(head));
|
||||
if (!myErrorWasReported.containsKey(head)) {
|
||||
myErrorWasReported.put(head, head);
|
||||
LOG.error("No references found at head " + head + " which corresponds to hash " + myHashGetter.fun(head));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -5,7 +5,6 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import com.intellij.vcs.log.ui.tables.AbstractVcsLogTableModel;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.awt.*;
|
||||
@@ -60,9 +59,6 @@ public class VcsLogColorManagerImpl implements VcsLogColorManager {
|
||||
@NotNull
|
||||
@Override
|
||||
public Color getRootColor(@NotNull VirtualFile root) {
|
||||
if (root == AbstractVcsLogTableModel.FAKE_ROOT) {
|
||||
return getDefaultRootColor();
|
||||
}
|
||||
Color color = myRoots2Colors.get(root);
|
||||
if (color == null) {
|
||||
LOG.error("No color record for root " + root + ". All roots: " + myRoots2Colors);
|
||||
|
||||
@@ -23,8 +23,6 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public abstract class AbstractVcsLogTableModel<CommitColumnClass> extends AbstractTableModel {
|
||||
|
||||
public static final VirtualFile FAKE_ROOT = NullVirtualFile.INSTANCE;
|
||||
|
||||
public static final int ROOT_COLUMN = 0;
|
||||
public static final int COMMIT_COLUMN = 1;
|
||||
public static final int AUTHOR_COLUMN = 2;
|
||||
|
||||
@@ -22,8 +22,8 @@ import com.intellij.vcs.log.VcsShortCommitDetails;
|
||||
import com.intellij.vcs.log.data.DataPack;
|
||||
import com.intellij.vcs.log.data.LoadMoreStage;
|
||||
import com.intellij.vcs.log.data.VcsLogDataHolder;
|
||||
import com.intellij.vcs.log.ui.render.GraphCommitCell;
|
||||
import com.intellij.vcs.log.ui.VcsLogUiImpl;
|
||||
import com.intellij.vcs.log.ui.render.GraphCommitCell;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -44,7 +44,7 @@ public class EmptyTableModel extends AbstractVcsLogTableModel<GraphCommitCell> {
|
||||
@NotNull
|
||||
@Override
|
||||
public VirtualFile getRoot(int rowIndex) {
|
||||
return FAKE_ROOT;
|
||||
throw new AssertionError("Root shouldn't be requested for empty table model. row: " + rowIndex);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -61,7 +61,8 @@ public class GraphTableModel extends AbstractVcsLogTableModel<GraphCommitCell> {
|
||||
Collection<VcsRef> refs = myDataPack.getRefsModel().refsToCommit(head);
|
||||
if (refs.isEmpty()) {
|
||||
LOG.error("No references pointing to head " + head + " identified for commit at row " + rowIndex);
|
||||
return FAKE_ROOT;
|
||||
// take the first root: it is the right choice in one-repo case, though it will likely fail in multi-repo case
|
||||
return myDataPack.getLogProviders().keySet().iterator().next();
|
||||
}
|
||||
return refs.iterator().next().getRoot();
|
||||
}
|
||||
|
||||
+1
-1
@@ -94,7 +94,7 @@ public class UnnecessarilyQualifiedStaticallyImportedElementInspection extends B
|
||||
if (!(qualifier instanceof PsiJavaCodeReferenceElement)) {
|
||||
return;
|
||||
}
|
||||
if (PsiTreeUtil.getParentOfType(reference, PsiReferenceExpression.class, PsiImportStatementBase.class) != null) {
|
||||
if (PsiTreeUtil.getParentOfType(reference, PsiImportStatementBase.class) != null) {
|
||||
return;
|
||||
}
|
||||
if (UnnecessarilyQualifiedStaticUsageInspection.isGenericReference(reference, (PsiJavaCodeReferenceElement)qualifier)) return;
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
<problems>
|
||||
<problem>
|
||||
<file>Test.java</file>
|
||||
<line>7</line>
|
||||
<problem_class severity="WARNING" attribute_key="NOT_USED_ELEMENT_ATTRIBUTES">Unnecessarily qualified statically imported element</problem_class>
|
||||
<description>Statically imported element 'foo' is unnecessarily qualified with <code>A</code> #loc</description>
|
||||
</problem>
|
||||
</problems>
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package p;
|
||||
|
||||
import static p.A.foo;
|
||||
|
||||
class StaticImport {
|
||||
void example() {
|
||||
A.foo().toString();
|
||||
}
|
||||
}
|
||||
|
||||
class A {
|
||||
static Object foo() {return null;}
|
||||
}
|
||||
+5
-1
@@ -21,7 +21,7 @@ public class UnnecessarilyQualifiedStaticallyImportedElementInspectionTest
|
||||
extends IGInspectionTestCase {
|
||||
|
||||
public void test() throws Exception {
|
||||
doTest("com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element",
|
||||
doTest("com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/simple",
|
||||
new UnnecessarilyQualifiedStaticallyImportedElementInspection());
|
||||
}
|
||||
|
||||
@@ -33,6 +33,10 @@ public class UnnecessarilyQualifiedStaticallyImportedElementInspectionTest
|
||||
doTest(getTestName(true));
|
||||
}
|
||||
|
||||
public void testChainedMethodCall() throws Exception {
|
||||
doTest(getTestName(true));
|
||||
}
|
||||
|
||||
private void doTest(String testName) throws Exception {
|
||||
doTest("com/siyeh/igtest/style/unnecessarily_qualified_statically_imported_element/" + testName,
|
||||
new UnnecessarilyQualifiedStaticallyImportedElementInspection());
|
||||
|
||||
@@ -90,8 +90,8 @@ public final class AntBuildMessageView extends JPanel implements DataProvider, O
|
||||
private AntBuildFileBase myBuildFile;
|
||||
private final String[] myTargets;
|
||||
private int myPriorityThreshold = PRIORITY_BRIEF;
|
||||
private int myErrorCount;
|
||||
private int myWarningCount;
|
||||
private volatile int myErrorCount;
|
||||
private volatile int myWarningCount;
|
||||
private volatile boolean myIsOutputPaused = false;
|
||||
|
||||
@NotNull
|
||||
@@ -109,7 +109,7 @@ public final class AntBuildMessageView extends JPanel implements DataProvider, O
|
||||
private final Runnable myFlushLogRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (myTreeView != null && myCommandsProcessedCount < myLog.size()) {
|
||||
if (myCommandsProcessedCount < myLog.size()) {
|
||||
if (!myIsOutputPaused) {
|
||||
new OutputFlusher().doFlush();
|
||||
myTreeView.scrollToLastMessage();
|
||||
|
||||
@@ -47,7 +47,7 @@ public class OutputParser{
|
||||
private final WeakReference<ProgressIndicator> myProgress;
|
||||
private final String myBuildName;
|
||||
private final OSProcessHandler myProcessHandler;
|
||||
private boolean isStopped;
|
||||
private volatile boolean isStopped;
|
||||
private List<String> myJavacMessages;
|
||||
private boolean myFirstLineProcessed;
|
||||
private boolean myStartedSuccessfully;
|
||||
|
||||
@@ -66,6 +66,13 @@
|
||||
bundle="org.jetbrains.idea.devkit.DevKitBundle"
|
||||
groupKey="inspections.group.name" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="org.jetbrains.idea.devkit.inspections.IntentionDescriptionNotFoundInspection"/>
|
||||
<localInspection language="JAVA"
|
||||
key="inspections.component.postfix.template.not.found.description.name"
|
||||
bundle="org.jetbrains.idea.devkit.DevKitBundle"
|
||||
groupKey="inspections.group.name"
|
||||
enabledByDefault="true"
|
||||
level="WARNING"
|
||||
implementationClass="org.jetbrains.idea.devkit.inspections.PostfixTemplateDescriptionNotFoundInspection"/>
|
||||
<localInspection shortName="ComponentRegistrationProblems"
|
||||
bundle="org.jetbrains.idea.devkit.DevKitBundle" key="inspections.registration.problems.name"
|
||||
groupKey="inspections.group.name"
|
||||
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
Checks if postfix template (completion) has a description.
|
||||
</body>
|
||||
</html>
|
||||
@@ -147,6 +147,9 @@ inspections.component.not.registered.option.ignore.non.public=Ignore non-public
|
||||
inspections.component.not.registered.quickfix.family=Register Component
|
||||
inspections.component.not.registered.quickfix.name=Register {0}
|
||||
inspections.component.not.registered.quickfix.error=Cannot Register {0}
|
||||
|
||||
inspections.component.postfix.template.not.found.description.name=Postfix template Description Checker
|
||||
|
||||
InspectionUseGrayColor=Use Gray
|
||||
ant.build.jar.comment=Build archive for plugin ''{0}''
|
||||
ant.build.jar.description=Build plugin archive for module ''{0}''
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.idea.devkit.inspections;
|
||||
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.codeInspection.ProblemHighlightType;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtilCore;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.devkit.inspections.quickfix.CreateHtmlDescriptionFix;
|
||||
import org.jetbrains.idea.devkit.util.PsiUtil;
|
||||
|
||||
abstract class DescriptionNotFoundInspectionBase extends DevKitInspectionBase {
|
||||
|
||||
@Override
|
||||
public ProblemDescriptor[] checkClass(@NotNull PsiClass aClass, @NotNull InspectionManager manager, boolean isOnTheFly) {
|
||||
final Project project = aClass.getProject();
|
||||
final PsiIdentifier nameIdentifier = aClass.getNameIdentifier();
|
||||
final Module module = ModuleUtilCore.findModuleForPsiElement(aClass);
|
||||
|
||||
if (nameIdentifier == null || module == null || !PsiUtil.isInstantiable(aClass)) return null;
|
||||
|
||||
final PsiClass base = JavaPsiFacade.getInstance(project).findClass(getClassName(), GlobalSearchScope.allScope(project));
|
||||
|
||||
if (base == null || !aClass.isInheritor(base, true)) return null;
|
||||
|
||||
String descriptionDir = getDescriptionDirName(aClass);
|
||||
if (StringUtil.isEmptyOrSpaces(descriptionDir)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (PsiDirectory description : getDescriptionsDirs(module)) {
|
||||
PsiDirectory dir = description.findSubdirectory(descriptionDir);
|
||||
if (dir == null) continue;
|
||||
final PsiFile descr = dir.findFile("description.html");
|
||||
if (descr != null) {
|
||||
if (!hasBeforeAndAfterTemplate(dir.getVirtualFile())) {
|
||||
PsiElement problem = aClass.getNameIdentifier();
|
||||
ProblemDescriptor problemDescriptor = manager.createProblemDescriptor(problem == null ? nameIdentifier : problem,
|
||||
getHasNotBeforeAfterError(),
|
||||
isOnTheFly,
|
||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false);
|
||||
return new ProblemDescriptor[]{problemDescriptor};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final PsiElement problem = aClass.getNameIdentifier();
|
||||
final ProblemDescriptor problemDescriptor = manager
|
||||
.createProblemDescriptor(problem == null ? nameIdentifier : problem,
|
||||
getHasNotDescriptionError(), isOnTheFly, new LocalQuickFix[]{getFix(module, descriptionDir)},
|
||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
|
||||
return new ProblemDescriptor[]{problemDescriptor};
|
||||
}
|
||||
|
||||
protected CreateHtmlDescriptionFix getFix(Module module, String descriptionDir) {
|
||||
return new CreateHtmlDescriptionFix(descriptionDir, module, true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getDescriptionDirName(PsiClass aClass) {
|
||||
String descriptionDir = "";
|
||||
PsiClass each = aClass;
|
||||
while (each != null) {
|
||||
String name = each.getName();
|
||||
if (StringUtil.isEmptyOrSpaces(name)) {
|
||||
return null;
|
||||
}
|
||||
descriptionDir = name + descriptionDir;
|
||||
each = each.getContainingClass();
|
||||
}
|
||||
return descriptionDir;
|
||||
}
|
||||
|
||||
private static boolean hasBeforeAndAfterTemplate(@NotNull VirtualFile dir) {
|
||||
boolean hasBefore = false;
|
||||
boolean hasAfter = false;
|
||||
|
||||
for (VirtualFile file : dir.getChildren()) {
|
||||
String name = file.getName();
|
||||
if (name.endsWith(".template")) {
|
||||
if (name.startsWith("before.")) {
|
||||
hasBefore = true;
|
||||
}
|
||||
else if (name.startsWith("after.")) {
|
||||
hasAfter = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hasBefore && hasAfter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabledByDefault() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected abstract String getClassName();
|
||||
|
||||
@NotNull
|
||||
protected abstract String getHasNotDescriptionError();
|
||||
|
||||
@NotNull
|
||||
protected abstract String getHasNotBeforeAfterError();
|
||||
|
||||
@NotNull
|
||||
protected abstract PsiDirectory[] getDescriptionsDirs(@NotNull Module module);
|
||||
}
|
||||
@@ -15,118 +15,57 @@
|
||||
*/
|
||||
package org.jetbrains.idea.devkit.inspections;
|
||||
|
||||
import com.intellij.codeInspection.InspectionManager;
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.codeInspection.ProblemHighlightType;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.JavaPsiFacade;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiPackage;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.idea.devkit.inspections.quickfix.CreateHtmlDescriptionFix;
|
||||
import org.jetbrains.idea.devkit.util.PsiUtil;
|
||||
|
||||
/**
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public class IntentionDescriptionNotFoundInspection extends DevKitInspectionBase{
|
||||
public class IntentionDescriptionNotFoundInspection extends DescriptionNotFoundInspectionBase {
|
||||
@NonNls private static final String INTENTION = "com.intellij.codeInsight.intention.IntentionAction";
|
||||
@NonNls private static final String INSPECTION_DESCRIPTIONS = "intentionDescriptions";
|
||||
|
||||
@Override
|
||||
public ProblemDescriptor[] checkClass(@NotNull PsiClass aClass, @NotNull InspectionManager manager, boolean isOnTheFly) {
|
||||
final Project project = aClass.getProject();
|
||||
final PsiIdentifier nameIdentifier = aClass.getNameIdentifier();
|
||||
final Module module = ModuleUtil.findModuleForPsiElement(aClass);
|
||||
|
||||
if (nameIdentifier == null || module == null || !PsiUtil.isInstantiable(aClass)) return null;
|
||||
|
||||
final PsiClass base = JavaPsiFacade.getInstance(project).findClass(INTENTION, GlobalSearchScope.allScope(project));
|
||||
|
||||
if (base == null || ! aClass.isInheritor(base, true)) return null;
|
||||
|
||||
String descriptionDir = getDescriptionDirName(aClass);
|
||||
if (StringUtil.isEmptyOrSpaces(descriptionDir)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (PsiDirectory description : getIntentionDescriptionsDirs(module)) {
|
||||
PsiDirectory dir = description.findSubdirectory(descriptionDir);
|
||||
if (dir == null) continue;
|
||||
final PsiFile descr = dir.findFile("description.html");
|
||||
if (descr != null) {
|
||||
if (!hasBeforeAndAfterTemplate(dir.getVirtualFile())) {
|
||||
PsiElement problem = aClass.getNameIdentifier();
|
||||
ProblemDescriptor problemDescriptor = manager.createProblemDescriptor(problem == null ? nameIdentifier : problem,
|
||||
"Intention must have 'before.*.template' and 'after.*.template' beside 'description.html'",
|
||||
isOnTheFly,
|
||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, false);
|
||||
return new ProblemDescriptor[]{problemDescriptor};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
final PsiElement problem = aClass.getNameIdentifier();
|
||||
final ProblemDescriptor problemDescriptor = manager
|
||||
.createProblemDescriptor(problem == null ? nameIdentifier : problem,
|
||||
"Intention does not have a description", isOnTheFly, new LocalQuickFix[]{new CreateHtmlDescriptionFix(descriptionDir, module, true)},
|
||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING);
|
||||
return new ProblemDescriptor[]{problemDescriptor};
|
||||
protected CreateHtmlDescriptionFix getFix(Module module, String descriptionDir) {
|
||||
return new CreateHtmlDescriptionFix(descriptionDir, module, true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String getDescriptionDirName(PsiClass aClass) {
|
||||
String descriptionDir = "";
|
||||
PsiClass each = aClass;
|
||||
while (each != null) {
|
||||
String name = each.getName();
|
||||
if (StringUtil.isEmptyOrSpaces(name)) {
|
||||
return null;
|
||||
}
|
||||
descriptionDir = name + descriptionDir;
|
||||
each = each.getContainingClass();
|
||||
}
|
||||
return descriptionDir;
|
||||
@NotNull
|
||||
protected String getClassName() {
|
||||
return INTENTION;
|
||||
}
|
||||
|
||||
private static boolean hasBeforeAndAfterTemplate(@NotNull VirtualFile dir) {
|
||||
boolean hasBefore = false;
|
||||
boolean hasAfter = false;
|
||||
@NotNull
|
||||
protected String getHasNotDescriptionError() {
|
||||
return "Intention does not have a description";
|
||||
}
|
||||
|
||||
for (VirtualFile file : dir.getChildren()) {
|
||||
String name = file.getName();
|
||||
if (name.endsWith(".template")) {
|
||||
if (name.startsWith("before.")) {
|
||||
hasBefore = true;
|
||||
}
|
||||
else if (name.startsWith("after.")) {
|
||||
hasAfter = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hasBefore && hasAfter;
|
||||
@NotNull
|
||||
protected String getHasNotBeforeAfterError() {
|
||||
return "Intention must have 'before.*.template' and 'after.*.template' beside 'description.html'";
|
||||
}
|
||||
|
||||
public static PsiDirectory[] getIntentionDescriptionsDirs(Module module) {
|
||||
final PsiPackage aPackage = JavaPsiFacade.getInstance(module.getProject()).findPackage(INSPECTION_DESCRIPTIONS);
|
||||
if (aPackage != null) {
|
||||
return aPackage.getDirectories(GlobalSearchScope.moduleWithDependenciesScope(module));
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return PsiDirectory.EMPTY_ARRAY;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected PsiDirectory[] getDescriptionsDirs(@NotNull Module module) {
|
||||
return getIntentionDescriptionsDirs(module);
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
public String getDisplayName() {
|
||||
@@ -137,9 +76,4 @@ public class IntentionDescriptionNotFoundInspection extends DevKitInspectionBase
|
||||
public String getShortName() {
|
||||
return "IntentionDescriptionNotFoundInspection";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabledByDefault() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.idea.devkit.inspections;
|
||||
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.psi.JavaPsiFacade;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import com.intellij.psi.PsiPackage;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.idea.devkit.DevKitBundle;
|
||||
import org.jetbrains.idea.devkit.inspections.quickfix.CreateHtmlDescriptionFix;
|
||||
import org.jetbrains.idea.devkit.inspections.quickfix.CreatePostfixTemplateHtmlDescriptionFix;
|
||||
|
||||
|
||||
public class PostfixTemplateDescriptionNotFoundInspection extends DescriptionNotFoundInspectionBase {
|
||||
|
||||
private static final String POSTFIX_TEMPLATES = "postfixTemplates";
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected PsiDirectory[] getDescriptionsDirs(@NotNull Module module) {
|
||||
return getPostfixTemplateDirectories(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CreateHtmlDescriptionFix getFix(Module module, String descriptionDir) {
|
||||
return new CreatePostfixTemplateHtmlDescriptionFix(descriptionDir, module);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static PsiDirectory[] getPostfixTemplateDirectories(Module module) {
|
||||
final PsiPackage aPackage = JavaPsiFacade.getInstance(module.getProject()).findPackage(POSTFIX_TEMPLATES);
|
||||
if (aPackage != null) {
|
||||
return aPackage.getDirectories(GlobalSearchScope.moduleWithDependenciesScope(module));
|
||||
}
|
||||
else {
|
||||
return PsiDirectory.EMPTY_ARRAY;
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getHasNotDescriptionError() {
|
||||
return "Postfix template does not have a description";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getHasNotBeforeAfterError() {
|
||||
return "Postfix template must have 'before.*.template' and 'after.*.template' beside 'description.html'";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected String getClassName() {
|
||||
return "com.intellij.codeInsight.template.postfix.templates.PostfixTemplate";
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return DevKitBundle.message("inspections.component.postfix.template.not.found.description.name");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getShortName() {
|
||||
return "PostfixTemplateDescriptionNotFound";
|
||||
}
|
||||
}
|
||||
@@ -57,75 +57,15 @@ import java.util.List;
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public class CreateHtmlDescriptionFix implements LocalQuickFix, Iconable {
|
||||
private final String myFilename;
|
||||
private final Module myModule;
|
||||
@NonNls private static final String TEMPLATE_NAME = "InspectionDescription.html";
|
||||
private final String myFilename;
|
||||
protected final Module myModule;
|
||||
private final boolean isIntention;
|
||||
|
||||
public CreateHtmlDescriptionFix(String filename, Module module, boolean isIntention) {
|
||||
myModule = module;
|
||||
this.isIntention = isIntention;
|
||||
myFilename = isIntention ? filename : filename + ".html";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return DevKitBundle.message("create.description.file");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
return "DevKit";
|
||||
}
|
||||
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
final PsiDirectory[] dirs;
|
||||
if (isIntention) {
|
||||
dirs = IntentionDescriptionNotFoundInspection.getIntentionDescriptionsDirs(myModule);
|
||||
}
|
||||
else {
|
||||
dirs = InspectionDescriptionNotFoundInspection.getInspectionDescriptionsDirs(myModule);
|
||||
}
|
||||
final List<VirtualFile> virtualFiles = getPotentialRoots(myModule, dirs);
|
||||
final VirtualFile[] roots = prepare(VfsUtil.toVirtualFileArray(virtualFiles));
|
||||
if (roots.length == 1) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
createDescription(roots[0]);
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
else {
|
||||
List<String> options = new ArrayList<String>();
|
||||
for (VirtualFile file : roots) {
|
||||
String path = file.getPresentableUrl() + File.separator + getDescriptionFolderName() + File.separator + myFilename;
|
||||
if (isIntention) {
|
||||
path += File.separator + "description.html";
|
||||
}
|
||||
options.add(path);
|
||||
}
|
||||
final JBList files = new JBList(ArrayUtil.toStringArray(options));
|
||||
files.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
final JBPopup popup = JBPopupFactory.getInstance()
|
||||
.createListPopupBuilder(files)
|
||||
.setTitle(DevKitBundle.message("select.target.location.of.description", myFilename))
|
||||
.setItemChoosenCallback(new Runnable() {
|
||||
public void run() {
|
||||
final int index = files.getSelectedIndex();
|
||||
if (0 <= index && index < roots.length) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
createDescription(roots[index]);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}).createPopup();
|
||||
final Editor editor = FileEditorManager.getInstance(myModule.getProject()).getSelectedTextEditor();
|
||||
if (editor == null) return;
|
||||
popup.showInBestPositionFor(editor);
|
||||
}
|
||||
myFilename = getNormalizedFileName(filename);
|
||||
}
|
||||
|
||||
private static List<VirtualFile> getPotentialRoots(Module module, PsiDirectory[] dirs) {
|
||||
@@ -147,6 +87,80 @@ public class CreateHtmlDescriptionFix implements LocalQuickFix, Iconable {
|
||||
}
|
||||
}
|
||||
|
||||
private String getNormalizedFileName(String filename) {
|
||||
return isIntention ? filename : filename + ".html";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return DevKitBundle.message("create.description.file");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
return "DevKit";
|
||||
}
|
||||
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
final PsiDirectory[] dirs;
|
||||
dirs = getDirectories();
|
||||
final List<VirtualFile> virtualFiles = getPotentialRoots(myModule, dirs);
|
||||
final VirtualFile[] roots = prepare(VfsUtil.toVirtualFileArray(virtualFiles));
|
||||
if (roots.length == 1) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
createDescription(roots[0]);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
List<String> options = new ArrayList<String>();
|
||||
for (VirtualFile file : roots) {
|
||||
String path = getPath(file);
|
||||
options.add(path);
|
||||
}
|
||||
final JBList files = new JBList(ArrayUtil.toStringArray(options));
|
||||
files.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
||||
final JBPopup popup = JBPopupFactory.getInstance()
|
||||
.createListPopupBuilder(files)
|
||||
.setTitle(DevKitBundle.message("select.target.location.of.description", myFilename))
|
||||
.setItemChoosenCallback(new Runnable() {
|
||||
public void run() {
|
||||
final int index = files.getSelectedIndex();
|
||||
if (0 <= index && index < roots.length) {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
createDescription(roots[index]);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}).createPopup();
|
||||
final Editor editor = FileEditorManager.getInstance(myModule.getProject()).getSelectedTextEditor();
|
||||
if (editor == null) return;
|
||||
popup.showInBestPositionFor(editor);
|
||||
}
|
||||
}
|
||||
|
||||
private String getPath(VirtualFile file) {
|
||||
String path = file.getPresentableUrl() + File.separator + getDescriptionFolderName() + File.separator + myFilename;
|
||||
if (isIntention) {
|
||||
path += File.separator + "description.html";
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
protected PsiDirectory[] getDirectories() {
|
||||
PsiDirectory[] dirs;
|
||||
if (isIntention) {
|
||||
dirs = IntentionDescriptionNotFoundInspection.getIntentionDescriptionsDirs(myModule);
|
||||
}
|
||||
else {
|
||||
dirs = InspectionDescriptionNotFoundInspection.getInspectionDescriptionsDirs(myModule);
|
||||
}
|
||||
return dirs;
|
||||
}
|
||||
|
||||
private void createDescription(VirtualFile root) {
|
||||
if (!root.isDirectory()) return;
|
||||
final PsiManager psiManager = PsiManager.getInstance(myModule.getProject());
|
||||
@@ -169,7 +183,8 @@ public class CreateHtmlDescriptionFix implements LocalQuickFix, Iconable {
|
||||
}
|
||||
}
|
||||
final FileTemplate descrTemplate = FileTemplateManager.getInstance().getJ2eeTemplate(TEMPLATE_NAME);
|
||||
final PsiElement template = FileTemplateUtil.createFromTemplate(descrTemplate, isIntention? "description.html" : myFilename, null, descrRoot);
|
||||
final PsiElement template =
|
||||
FileTemplateUtil.createFromTemplate(descrTemplate, getNewFileName(), null, descrRoot);
|
||||
if (template instanceof PsiFile) {
|
||||
final VirtualFile file = ((PsiFile)template).getVirtualFile();
|
||||
if (file != null) {
|
||||
@@ -181,6 +196,10 @@ public class CreateHtmlDescriptionFix implements LocalQuickFix, Iconable {
|
||||
}
|
||||
}
|
||||
|
||||
private String getNewFileName() {
|
||||
return isIntention ? "description.html" : myFilename;
|
||||
}
|
||||
|
||||
public Icon getIcon(int flags) {
|
||||
return new LayeredIcon(AllIcons.FileTypes.Html, AllIcons.Actions.New);
|
||||
}
|
||||
@@ -205,7 +224,7 @@ public class CreateHtmlDescriptionFix implements LocalQuickFix, Iconable {
|
||||
return false;
|
||||
}
|
||||
|
||||
private String getDescriptionFolderName() {
|
||||
protected String getDescriptionFolderName() {
|
||||
return isIntention ? "intentionDescriptions" : "inspectionDescriptions";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.idea.devkit.inspections.quickfix;
|
||||
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.psi.PsiDirectory;
|
||||
import org.jetbrains.idea.devkit.inspections.PostfixTemplateDescriptionNotFoundInspection;
|
||||
|
||||
|
||||
public class CreatePostfixTemplateHtmlDescriptionFix extends CreateHtmlDescriptionFix {
|
||||
|
||||
public CreatePostfixTemplateHtmlDescriptionFix(String filename, Module module) {
|
||||
super(filename, module, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PsiDirectory[] getDirectories() {
|
||||
return PostfixTemplateDescriptionNotFoundInspection.getPostfixTemplateDirectories(myModule);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDescriptionFolderName() {
|
||||
return "postfixTemplates";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate;
|
||||
|
||||
public class <caret>MyQuickFixTemplate extends PostfixTemplate {
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate;
|
||||
|
||||
public class <warning descr="Postfix template does not have a description">MyTemplate</warning> extends PostfixTemplate {
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate;
|
||||
|
||||
public class MyTemplateWithDescription extends PostfixTemplate {
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate;
|
||||
|
||||
public class <warning descr="Postfix template must have 'before.*.template' and 'after.*.template' beside 'description.html'">MyTemplateWithoutBeforeAfter</warning> extends PostfixTemplate{
|
||||
|
||||
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
test after
|
||||
+1
@@ -0,0 +1 @@
|
||||
test before
|
||||
+1
@@ -0,0 +1 @@
|
||||
test description
|
||||
+1
@@ -0,0 +1 @@
|
||||
test description
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.jetbrains.idea.devkit.codeInsight;
|
||||
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.openapi.application.PluginPathManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
|
||||
import org.jetbrains.idea.devkit.inspections.PostfixTemplateDescriptionNotFoundInspection;
|
||||
|
||||
public class PostfixTemplateInspectionTest extends JavaCodeInsightFixtureTestCase {
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return PluginPathManager.getPluginHomePathRelative("devkit") + "/testData/codeInsight/postfixTemplates";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
myFixture.enableInspections(PostfixTemplateDescriptionNotFoundInspection.class);
|
||||
myFixture.addClass("package com.intellij.codeInsight.template.postfix.templates; public class PostfixTemplate {}");
|
||||
}
|
||||
|
||||
public void testHighlightingForDescription() {
|
||||
myFixture.testHighlighting("MyTemplate.java");
|
||||
}
|
||||
|
||||
public void testNoHighlighting() {
|
||||
myFixture.copyDirectoryToProject("postfixTemplates", "postfixTemplates");
|
||||
myFixture.testHighlighting("MyTemplateWithDescription.java");
|
||||
}
|
||||
|
||||
public void testHighlightingForBeforeAfter() {
|
||||
myFixture.copyDirectoryToProject("postfixTemplates", "postfixTemplates");
|
||||
myFixture.testHighlighting("MyTemplateWithoutBeforeAfter.java");
|
||||
}
|
||||
|
||||
public void testQuickFix() {
|
||||
myFixture.configureByFiles("MyQuickFixTemplate.java");
|
||||
IntentionAction item = myFixture.findSingleIntention("Create Description File");
|
||||
myFixture.launchAction(item);
|
||||
|
||||
VirtualFile path = myFixture.findFileInTempDir("postfixTemplates/MyQuickFixTemplate/description.html");
|
||||
assertNotNull(path);
|
||||
assertTrue(path.exists());
|
||||
}
|
||||
}
|
||||
@@ -228,7 +228,11 @@ public class GitBranchUtil {
|
||||
String branchName = stdName.substring(slash + 1);
|
||||
GitRemote remote = findRemoteByName(remoteName, remotes);
|
||||
if (remote == null) {
|
||||
return null;
|
||||
// user may remove the remote section from .git/config, but leave remote refs untouched in .git/refs/remotes
|
||||
LOG.info(String.format("No remote found with the name [%s]. All remotes: %s", remoteName, remotes));
|
||||
GitRemote fakeRemote = new GitRemote(remoteName, ContainerUtil.<String>emptyList(), Collections.<String>emptyList(),
|
||||
Collections.<String>emptyList(), Collections.<String>emptyList());
|
||||
return new GitStandardRemoteBranch(fakeRemote, branchName, hash);
|
||||
}
|
||||
return new GitStandardRemoteBranch(remote, branchName, hash);
|
||||
}
|
||||
@@ -241,8 +245,6 @@ public class GitBranchUtil {
|
||||
return remote;
|
||||
}
|
||||
}
|
||||
// user may remove the remote section from .git/config, but leave remote refs untouched in .git/refs/remotes
|
||||
LOG.info(String.format("No remote found with the name [%s]. All remotes: %s", remoteName, remotes));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -135,6 +135,13 @@ public class GitConfig {
|
||||
*/
|
||||
@NotNull
|
||||
static GitConfig read(@NotNull GitPlatformFacade platformFacade, @NotNull File configFile) {
|
||||
GitConfig emptyConfig = new GitConfig(Collections.<Remote>emptyList(), Collections.<Url>emptyList(),
|
||||
Collections.<BranchConfig>emptyList());
|
||||
if (!configFile.exists()) {
|
||||
LOG.info("No .git/config file at " + configFile.getPath());
|
||||
return emptyConfig;
|
||||
}
|
||||
|
||||
Ini ini = new Ini();
|
||||
ini.getConfig().setMultiOption(true); // duplicate keys (e.g. url in [remote])
|
||||
ini.getConfig().setTree(false); // don't need tree structure: it corrupts url in section name (e.g. [url "http://github.com/"]
|
||||
@@ -143,7 +150,7 @@ public class GitConfig {
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.error(new RepoStateException("Couldn't load .git/config file at " + configFile.getPath(), e));
|
||||
return new GitConfig(Collections.<Remote>emptyList(), Collections.<Url>emptyList(), Collections.<BranchConfig>emptyList());
|
||||
return emptyConfig;
|
||||
}
|
||||
|
||||
IdeaPluginDescriptor plugin = platformFacade.getPluginByClassName(GitConfig.class.getName());
|
||||
|
||||
@@ -39,7 +39,7 @@ import java.util.List;
|
||||
* </p>
|
||||
* <p>
|
||||
* GitRemote instance constructed by {@link GitConfig#read(GitPlatformFacade, File)}} has all these rules applied.
|
||||
* Thus, for example, if only one {@code url} and no {@code pushUrls} are defined for the remote,
|
||||
* Thus, for example, if only one {@code url} and no {@code pushUrls} are defined for the remote,
|
||||
* both {@link #getUrls()} and {@link #getPushUrls()} will return this url. <br/>
|
||||
* This is made to avoid urls transformation logic from the code using GitRemote, leaving it all in GitConfig parsing.
|
||||
* </p>
|
||||
@@ -47,14 +47,14 @@ import java.util.List;
|
||||
* Same applies to fetch and push specs: {@link #getPushRefSpecs()} returns the spec,
|
||||
* even if there are no separate record in {@code .git/config}
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* NB: Not all remote preferences (defined in {@code .git/config} are stored in the object.
|
||||
* If some additional data is needed, add the field, getter, constructor parameter and populate it in {@link GitConfig}.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <p>Remotes are compared (via equals, hashcode and compareTo) only by names.</p>
|
||||
*
|
||||
*
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public final class GitRemote implements Comparable<GitRemote> {
|
||||
@@ -80,8 +80,8 @@ public final class GitRemote implements Comparable<GitRemote> {
|
||||
@NotNull final List<String> myFetchRefSpecs;
|
||||
@NotNull private final List<String> myPushRefSpecs;
|
||||
|
||||
GitRemote(@NotNull String name, @NotNull List<String> urls, @NotNull Collection<String> pushUrls,
|
||||
@NotNull List<String> fetchRefSpecs, @NotNull List<String> pushRefSpecs) {
|
||||
public GitRemote(@NotNull String name, @NotNull List<String> urls, @NotNull Collection<String> pushUrls,
|
||||
@NotNull List<String> fetchRefSpecs, @NotNull List<String> pushRefSpecs) {
|
||||
myName = name;
|
||||
myUrls = urls;
|
||||
myPushUrls = pushUrls;
|
||||
|
||||
@@ -16,10 +16,14 @@
|
||||
package git4idea.repo;
|
||||
|
||||
import com.intellij.dvcs.repo.Repository;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import git4idea.GitLocalBranch;
|
||||
import git4idea.GitRemoteBranch;
|
||||
import git4idea.test.GitSingleRepoTest;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
|
||||
import static git4idea.test.GitExecutor.git;
|
||||
import static git4idea.test.GitScenarios.commit;
|
||||
@@ -46,4 +50,24 @@ public class GitRepositoryReaderNewTest extends GitSingleRepoTest {
|
||||
assertEquals("State value is incorrect", Repository.State.REBASING, state);
|
||||
}
|
||||
|
||||
// inspired by IDEA-124052
|
||||
public void test_remote_reference_without_remote() {
|
||||
final String INVALID_REMOTE = "invalid-remote";
|
||||
final String INVALID_REMOTE_BRANCH = "master";
|
||||
git("update-ref refs/remotes/" + INVALID_REMOTE + "/" + INVALID_REMOTE_BRANCH + " HEAD");
|
||||
|
||||
File gitDir = new File(myRepo.getRoot().getPath(), ".git");
|
||||
GitRepositoryReader reader = new GitRepositoryReader(gitDir);
|
||||
GitConfig config = GitConfig.read(myPlatformFacade, new File(gitDir, "config"));
|
||||
Collection<GitRemote> remotes = config.parseRemotes();
|
||||
|
||||
Collection<GitRemoteBranch> remoteBranches = reader.readBranches(remotes).getRemoteBranches();
|
||||
assertTrue("Remote branch not found", ContainerUtil.exists(remoteBranches, new Condition<GitRemoteBranch>() {
|
||||
@Override
|
||||
public boolean value(GitRemoteBranch branch) {
|
||||
return branch.getNameForLocalOperations().equals(INVALID_REMOTE + "/" + INVALID_REMOTE_BRANCH);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import com.intellij.ide.fileTemplates.FileTemplateDescriptor;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.util.PathUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.groovy.GroovyFileType;
|
||||
|
||||
@@ -16,10 +16,11 @@ import com.google.common.base.Objects;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vcs.FilePath;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.vcsUtil.VcsUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.zmlx.hg4idea.util.HgUtil;
|
||||
|
||||
import java.io.File;
|
||||
@@ -53,10 +54,11 @@ public class HgFile {
|
||||
return file;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Nullable
|
||||
public String getRelativePath() {
|
||||
if (relativePath == null) {
|
||||
relativePath = buildRelativePath(VfsUtil.virtualToIoFile(vcsRoot), file);
|
||||
//For configuration like "d:/.hg" File.getParent method has minimal prefix length, so vcsRoot will be "d:", getParent will be "d:/".
|
||||
relativePath = FileUtil.getRelativePath(VfsUtilCore.virtualToIoFile(vcsRoot), file);
|
||||
}
|
||||
return relativePath;
|
||||
}
|
||||
@@ -66,17 +68,6 @@ public class HgFile {
|
||||
return VcsUtil.getFilePath(file);
|
||||
}
|
||||
|
||||
private static String buildRelativePath(File anchestor, File descendant) {
|
||||
if (anchestor.equals(descendant)) {
|
||||
return ".";
|
||||
}
|
||||
if (anchestor.equals(descendant.getParentFile())) {
|
||||
return descendant.getName();
|
||||
}
|
||||
return buildRelativePath(anchestor, descendant.getParentFile())
|
||||
+ File.separator + descendant.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
|
||||
@@ -17,10 +17,13 @@ package com.intellij.execution.junit;
|
||||
|
||||
import com.intellij.CommonBundle;
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.OrderEntryFix;
|
||||
import com.intellij.codeInsight.intention.AddAnnotationFix;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.fileTemplates.FileTemplateDescriptor;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.projectRoots.ex.JavaSdkUtil;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.psi.*;
|
||||
@@ -34,6 +37,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
import javax.swing.*;
|
||||
|
||||
public class JUnit4Framework extends JavaTestFramework {
|
||||
private static final Logger LOG = Logger.getInstance("#" + JUnit4Framework.class.getName());
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return "JUnit4";
|
||||
@@ -153,6 +158,16 @@ public class JUnit4Framework extends JavaTestFramework {
|
||||
return new FileTemplateDescriptor("JUnit4 Test Class.java");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupLibrary(Module module) {
|
||||
try {
|
||||
OrderEntryFix.addJUnit4Library(false, module);
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
LOG.info(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isParameterized(PsiClass clazz) {
|
||||
final PsiAnnotation annotation = AnnotationUtil.findAnnotation(clazz, JUnitUtil.RUN_WITH);
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.intellij.ide.util.ClassFilter;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiClass;
|
||||
@@ -30,6 +31,7 @@ import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.PsiUtilCore;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.model.java.JavaModuleSourceRootTypes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -59,7 +61,9 @@ public class TestClassFilter implements ClassFilter.ClassFilterWithScope {
|
||||
(aClass.isInheritor(myBase, true) || JUnitUtil.isTestClass(aClass))) {
|
||||
final CompilerConfiguration compilerConfiguration = CompilerConfiguration.getInstance(getProject());
|
||||
final VirtualFile virtualFile = PsiUtilCore.getVirtualFile(aClass);
|
||||
return !compilerConfiguration.isExcludedFromCompilation(virtualFile) && !compilerConfiguration.isResourceFile(virtualFile);
|
||||
if (virtualFile == null) return false;
|
||||
return !compilerConfiguration.isExcludedFromCompilation(virtualFile) &&
|
||||
!ProjectRootManager.getInstance(myProject).getFileIndex().isUnderSourceRootOfType(virtualFile, JavaModuleSourceRootTypes.RESOURCES);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -98,6 +98,11 @@ public class JUnitEntryPoint extends EntryPoint {
|
||||
|
||||
@Override
|
||||
public String[] getIgnoreAnnotations() {
|
||||
return new String[]{"org.junit.Rule", "org.mockito.Mock", "org.mockito.InjectMocks", "org.junit.ClassRule", "org.junit.experimental.theories.DataPoint"};
|
||||
return new String[]{"org.junit.Rule",
|
||||
"org.mockito.Mock",
|
||||
"org.mockito.Spy",
|
||||
"org.mockito.InjectMocks",
|
||||
"org.junit.ClassRule",
|
||||
"org.junit.experimental.theories.DataPoint"};
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,9 @@ import com.intellij.openapi.fileTypes.FileTypeManager;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.module.ModuleUtil;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.project.DumbModeTask;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.*;
|
||||
@@ -156,27 +159,45 @@ public class PythonLanguageLevelPusher implements FilePropertyPusher<LanguageLev
|
||||
}
|
||||
}
|
||||
|
||||
public void afterRootsChanged(@NotNull Project project) {
|
||||
Set<Sdk> updatedSdks = new HashSet<Sdk>();
|
||||
final Module[] modules = ModuleManager.getInstance(project).getModules();
|
||||
boolean needReparseOpenFiles = false;
|
||||
for (Module module : modules) {
|
||||
Sdk newSdk = PythonSdkType.findPythonSdk(module);
|
||||
if (myModuleSdks.containsKey(module)) {
|
||||
Sdk oldSdk = myModuleSdks.get(module);
|
||||
if ((newSdk != null || oldSdk != null) && newSdk != oldSdk) {
|
||||
needReparseOpenFiles = true;
|
||||
public void afterRootsChanged(@NotNull final Project project) {
|
||||
final Runnable updateLanguageLevel = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final Set<Sdk> updatedSdks = new HashSet<Sdk>();
|
||||
final Module[] modules = ModuleManager.getInstance(project).getModules();
|
||||
boolean needReparseOpenFiles = false;
|
||||
for (Module module : modules) {
|
||||
Sdk newSdk = PythonSdkType.findPythonSdk(module);
|
||||
if (myModuleSdks.containsKey(module)) {
|
||||
Sdk oldSdk = myModuleSdks.get(module);
|
||||
if ((newSdk != null || oldSdk != null) && newSdk != oldSdk) {
|
||||
needReparseOpenFiles = true;
|
||||
}
|
||||
}
|
||||
myModuleSdks.put(module, newSdk);
|
||||
if (newSdk != null && !updatedSdks.contains(newSdk)) {
|
||||
updatedSdks.add(newSdk);
|
||||
updateSdkLanguageLevel(project, newSdk);
|
||||
}
|
||||
}
|
||||
final boolean finalNeedReparseOpenFiles = needReparseOpenFiles;
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (finalNeedReparseOpenFiles) {
|
||||
FileContentUtil.reparseFiles(project, Collections.<VirtualFile>emptyList(), true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
myModuleSdks.put(module, newSdk);
|
||||
if (newSdk != null && !updatedSdks.contains(newSdk)) {
|
||||
updatedSdks.add(newSdk);
|
||||
updateSdkLanguageLevel(project, newSdk);
|
||||
};
|
||||
final DumbModeTask task = new DumbModeTask() {
|
||||
@Override
|
||||
public void performInDumbMode(@NotNull ProgressIndicator indicator) {
|
||||
ApplicationManager.getApplication().runReadAction(updateLanguageLevel);
|
||||
}
|
||||
}
|
||||
if (needReparseOpenFiles) {
|
||||
FileContentUtil.reparseFiles(project, Collections.<VirtualFile>emptyList(), true);
|
||||
}
|
||||
};
|
||||
DumbService.getInstance(project).queueTask(task);
|
||||
}
|
||||
|
||||
private void updateSdkLanguageLevel(Project project, Sdk sdk) {
|
||||
|
||||
@@ -287,6 +287,7 @@ public class PythonSdkType extends SdkType {
|
||||
public void consume(@Nullable Sdk sdk) {
|
||||
if (sdk != null) {
|
||||
sdk.putUserData(SDK_CREATOR_COMPONENT_KEY, new WeakReference<Component>(parentComponent));
|
||||
sdkCreatedCallback.consume(sdk);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -499,6 +500,11 @@ public class PythonSdkType extends SdkType {
|
||||
setupSdkPaths(sdk, project, ownerComponent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setupSdkPaths(Sdk sdk, SdkModel sdkModel) {
|
||||
return true; // run setupSdkPaths only once (from PythonSdkDetailsStep). Skip this from showCustomCreateUI
|
||||
}
|
||||
|
||||
public static void setupSdkPaths(Sdk sdk, @Nullable Project project, @Nullable Component ownerComponent) {
|
||||
final SdkModificator sdkModificator = sdk.getSdkModificator();
|
||||
final boolean success = setupSdkPaths(project, ownerComponent, sdk, sdkModificator);
|
||||
|
||||
Reference in New Issue
Block a user