Merge remote branch 'origin/master'

This commit is contained in:
irengrig
2012-12-12 16:19:30 +04:00
37 changed files with 366 additions and 186 deletions
@@ -26,6 +26,8 @@ import java.util.Collection;
public interface DirtyFilesHolder<R extends BuildRootDescriptor, T extends BuildTarget<R>> {
void processDirtyFiles(@NotNull FileProcessor<R, T> processor) throws IOException;
boolean hasDirtyFiles() throws IOException;
boolean hasRemovedFiles();
@NotNull
@@ -15,13 +15,17 @@
*/
package org.jetbrains.jps.builders.impl;
import com.intellij.openapi.util.Ref;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.builders.BuildRootDescriptor;
import org.jetbrains.jps.builders.BuildTarget;
import org.jetbrains.jps.builders.DirtyFilesHolder;
import org.jetbrains.jps.builders.FileProcessor;
import org.jetbrains.jps.incremental.CompileContext;
import org.jetbrains.jps.incremental.Utils;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
@@ -36,6 +40,19 @@ public abstract class DirtyFilesHolderBase<R extends BuildRootDescriptor, T exte
myContext = context;
}
@Override
public boolean hasDirtyFiles() throws IOException {
final Ref<Boolean> hasDirtyFiles = Ref.create(false);
processDirtyFiles(new FileProcessor<R, T>() {
@Override
public boolean apply(T target, File file, R root) throws IOException {
hasDirtyFiles.set(true);
return false;
}
});
return hasDirtyFiles.get();
}
@Override
public boolean hasRemovedFiles() {
Map<BuildTarget<?>, Collection<String>> map = Utils.REMOVED_SOURCES_KEY.get(myContext);
@@ -292,11 +292,15 @@ final class BuildSession implements Runnable, CanceledStatus {
}
final Timestamps timestamps = pd.timestamps.getStorage();
boolean cacheCleared = false;
for (String deleted : event.getDeletedPathsList()) {
final File file = new File(deleted);
Collection<BuildRootDescriptor> descriptor = pd.getBuildRootIndex().findAllParentDescriptors(file, null, null);
if (!descriptor.isEmpty()) {
if (!cacheCleared) {
pd.getFSCache().clear();
cacheCleared = true;
}
if (Utils.IS_TEST_MODE) {
LOG.info("Applying deleted path from fs event: " + file.getPath());
}
@@ -323,6 +327,10 @@ final class BuildSession implements Runnable, CanceledStatus {
}
long stamp = timestamps.getStamp(file, descriptor.getTarget());
if (stamp != fileStamp) {
if (!cacheCleared) {
pd.getFSCache().clear();
cacheCleared = true;
}
pd.fsState.markDirty(null, file, descriptor, timestamps, saveEventStamp);
}
}
@@ -15,10 +15,12 @@
*/
package org.jetbrains.jps.cmdline;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.builders.BuildRootIndex;
import org.jetbrains.jps.builders.BuildTargetIndex;
import org.jetbrains.jps.builders.logging.BuildLoggingManager;
import org.jetbrains.jps.incremental.CompilerEncodingConfiguration;
import org.jetbrains.jps.incremental.FSCache;
import org.jetbrains.jps.incremental.fs.BuildFSState;
import org.jetbrains.jps.incremental.storage.BuildDataManager;
import org.jetbrains.jps.incremental.storage.BuildTargetsState;
@@ -54,6 +56,7 @@ public final class ProjectDescriptor {
private final BuildRootIndex myBuildRootIndex;
private final BuildTargetIndex myBuildTargetIndex;
private final IgnoredFileIndex myIgnoredFileIndex;
private FSCache myFSCache = FSCache.NO_CACHE;
public ProjectDescriptor(JpsModel model,
BuildFSState fsState,
@@ -84,6 +87,15 @@ public final class ProjectDescriptor {
myTargetsState = targetsState;
}
@NotNull
public FSCache getFSCache() {
return myFSCache;
}
public void setFSCache(FSCache cache) {
myFSCache = cache == null? FSCache.NO_CACHE : cache;
}
public BuildRootIndex getBuildRootIndex() {
return myBuildRootIndex;
}
@@ -69,6 +69,4 @@ public interface CompileContext extends UserDataHolder, MessageHandler {
void markNonIncremental(ModuleBuildTarget target);
void clearNonIncrementalMark(ModuleBuildTarget target);
FSCache getFSCache();
}
@@ -57,7 +57,6 @@ public class CompileContextImpl extends UserDataHolderBase implements CompileCon
private volatile float myDone = -1.0f;
private EventDispatcher<BuildListener> myListeners = EventDispatcher.create(BuildListener.class);
private Map<JpsModule, ProcessorConfigProfile> myAnnotationProcessingProfileMap;
private final FSCache myFSCache;
public CompileContextImpl(CompileScope scope,
ProjectDescriptor pd, boolean isMake,
@@ -74,9 +73,6 @@ public class CompileContextImpl extends UserDataHolderBase implements CompileCon
myIsMake = !isProjectRebuild && isMake;
myDelegateMessageHandler = delegateMessageHandler;
myProjectPaths = new ProjectPaths(pd.getProject());
// in project rebuild mode performance gain is hard to observe, so it is better to save memory
// in make mode it is critical to traverse file system as fast as possible, so we choose speed over memory savings
myFSCache = isProjectRebuild? FSCache.NO_CACHE : new FSCache();
}
@Override
@@ -226,8 +222,4 @@ public class CompileContextImpl extends UserDataHolderBase implements CompileCon
public ProjectDescriptor getProjectDescriptor() {
return myProjectDescriptor;
}
public FSCache getFSCache() {
return myFSCache;
}
}
@@ -150,7 +150,7 @@ public class FSOperations {
if (filter == null) {
context.getProjectDescriptor().fsState.clearRecompile(rd);
}
final FSCache fsCache = rd.canUseFileCache() ? context.getFSCache() : FSCache.NO_CACHE;
final FSCache fsCache = rd.canUseFileCache() ? context.getProjectDescriptor().getFSCache() : FSCache.NO_CACHE;
traverseRecursively(context, rd, rd.getRootFile(), timestamps, forceMarkDirty, currentFiles, filter, fsCache);
}
}
@@ -320,6 +320,9 @@ public class IncProjectBuilder {
final CompileContextImpl context = new CompileContextImpl(scope, myProjectDescriptor, isMake, isProjectRebuild, myMessageDispatcher,
myBuilderParams, myCancelStatus
);
// in project rebuild mode performance gain is hard to observe, so it is better to save memory
// in make mode it is critical to traverse file system as fast as possible, so we choose speed over memory savings
myProjectDescriptor.setFSCache(isProjectRebuild? FSCache.NO_CACHE : new FSCache());
JavaBuilderUtil.CONSTANT_SEARCH_SERVICE.set(context, myConstantSearch);
return context;
}
@@ -15,6 +15,7 @@
*/
package com.intellij.openapi.editor.colors;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.util.DefaultJDOMExternalizer;
import com.intellij.openapi.util.InvalidDataException;
@@ -32,6 +33,7 @@ import org.jetbrains.annotations.NotNull;
public final class TextAttributesKey implements Comparable<TextAttributesKey>, JDOMExternalizable {
private static final TextAttributes NULL_ATTRIBUTES = new TextAttributes();
private static final ConcurrentHashMap<String, TextAttributesKey> ourRegistry = new ConcurrentHashMap<String, TextAttributesKey>();
private static final TextAttributeKeyDefaultsProvider OUR_DEFAULTS_PROVIDER = ServiceManager.getService(TextAttributeKeyDefaultsProvider.class);
public String myExternalName;
public TextAttributes myDefaultAttributes = NULL_ATTRIBUTES;
@@ -106,8 +108,8 @@ public final class TextAttributesKey implements Comparable<TextAttributesKey>, J
if (myDefaultAttributes == NULL_ATTRIBUTES) {
// E.g. if one text key reuse default attributes of some other predefined key
myDefaultAttributes = null;
if (myDefaultsProvider != null)
myDefaultAttributes = myDefaultsProvider.getDefaultAttributes(this);
if (OUR_DEFAULTS_PROVIDER != null)
myDefaultAttributes = OUR_DEFAULTS_PROVIDER.getDefaultAttributes(this);
}
return myDefaultAttributes;
}
@@ -147,6 +149,4 @@ public final class TextAttributesKey implements Comparable<TextAttributesKey>, J
public interface TextAttributeKeyDefaultsProvider {
TextAttributes getDefaultAttributes(TextAttributesKey key);
}
public static TextAttributeKeyDefaultsProvider myDefaultsProvider;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2012 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.
@@ -27,6 +27,7 @@ package com.intellij.codeInspection;
* to retrieve the PSI context the fix will work on.
*
* @author max
* @see LocalQuickFixBase
* @see com.intellij.codeInspection.ProblemDescriptor
* @see com.intellij.openapi.util.Iconable
*/
@@ -0,0 +1,62 @@
/*
* Copyright 2000-2012 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.codeInspection;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
/**
* @author Konstantin Bulenkov
*/
public abstract class LocalQuickFixBase implements LocalQuickFix {
private final String myName;
private final String myFamilyName;
/**
*
* @param name the name of the quick fix
*/
protected LocalQuickFixBase(@NotNull String name) {
this(name, name);
}
/**
*
* @param name the name of the quick fix
* @param familyName text to appear in "Apply Fix" popup when multiple Quick Fixes exist (in the results of batch code inspection). For example,
* if the name of the quickfix is "Create template &lt;filename&gt", the return value of getFamilyName() should be "Create template".
* If the name of the quickfix does not depend on a specific element, simply return getName().
*/
protected LocalQuickFixBase(@NotNull String name, @NotNull String familyName) {
myName = name;
myFamilyName = familyName;
}
@NotNull
@Override
public String getName() {
return myName;
}
@NotNull
@Override
public String getFamilyName() {
return myFamilyName;
}
@Override
public abstract void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor);
}
@@ -68,7 +68,14 @@ public abstract class InspectionToolWrapper<T extends InspectionProfileEntry, E
if (myTool == null) {
//noinspection unchecked
myTool = (T)myEP.instantiateTool();
LOG.assertTrue(myTool.getShortName().equals(myEP.getShortName()), "myTool: " + myTool.getShortName() + "; ep.shortName " + myEP.getShortName());
if (!myTool.getShortName().equals(myEP.getShortName())) {
LOG.error("Short name not matched for " +
myTool.getClass() +
": getShortName() = " +
myTool.getShortName() +
"; ep.shortName = " +
myEP.getShortName());
}
}
return myTool;
}
@@ -377,10 +377,6 @@ public class GridCellImpl implements GridCell {
}
public void saveUiState() {
String key = getDimensionKey();
if (key == null)
return;
saveProportions();
for (Content each : myContents.getKeys()) {
@@ -393,11 +389,11 @@ public class GridCellImpl implements GridCell {
final DimensionService service = DimensionService.getInstance();
final Dimension size = myContext.getContentManager().getComponent().getSize();
service.setSize(key, size, myContext.getProject());
service.setSize(getDimensionKey(), size, myContext.getProject());
if (myContext.getWindow() != 0) {
final Window frame = SwingUtilities.getWindowAncestor(myPlaceholder);
if (frame != null) {
service.setLocation(key, frame.getLocationOnScreen());
service.setLocation(getDimensionKey(), frame.getLocationOnScreen());
}
}
}
@@ -456,26 +452,16 @@ public class GridCellImpl implements GridCell {
@Nullable
public Point getLocation() {
String key = getDimensionKey();
if (key == null)
return null;
return DimensionService.getInstance().getLocation(key, myContext.getProject());
return DimensionService.getInstance().getLocation(getDimensionKey(), myContext.getProject());
}
@Nullable
public Dimension getSize() {
String key = getDimensionKey();
if (key == null)
return null;
return DimensionService.getInstance().getSize(key, myContext.getProject());
return DimensionService.getInstance().getSize(getDimensionKey(), myContext.getProject());
}
@Nullable
private String getDimensionKey() {
Tab tab = myContainer.getTab();
if (tab == null)
return null;
return "GridCell.Tab." + tab.getIndex() + "." + myPlaceInGrid.name();
return "GridCell.Tab." + myContainer.getTab().getIndex() + "." + myPlaceInGrid.name();
}
public boolean isValidForCalculateProportions() {
@@ -221,7 +221,7 @@ public class RunnerContentUi implements ContentUI, Disposable, CellTransform.Fac
public void beforeSelectionChanged(TabInfo oldSelection, TabInfo newSelection) {
if (oldSelection != null && !isStateBeingRestored()) {
final GridImpl grid = getGridFor(oldSelection);
if (grid != null) {
if (grid != null && getTabFor(grid) != null) {
grid.saveUiState();
}
}
@@ -118,18 +118,15 @@ public class EditorColorsManagerImpl extends EditorColorsManager implements Name
loadAllSchemes();
setGlobalScheme(myDefaultColorSchemesManager.getAllSchemes()[0]);
}
TextAttributesKey.myDefaultsProvider = new TextAttributesKey.TextAttributeKeyDefaultsProvider() {
final boolean dark = UIUtil.isUnderDarcula() && getScheme("Darcula") != null;
@Override
public TextAttributes getDefaultAttributes(TextAttributesKey key) {
// It is reasonable to fetch attributes from Default color scheme. Otherwise if we launch IDE and then
// try switch from custom colors scheme (e.g. with dark background) to default one. Editor will show
// incorrect highlighting with "traces" of color scheme which was active during IDE startup.
final EditorColorsScheme defaultColorScheme = getScheme(dark ? "Darcula" : EditorColorsScheme.DEFAULT_SCHEME_NAME);
return defaultColorScheme.getAttributes(key);
}
};
public TextAttributes getDefaultAttributes(TextAttributesKey key) {
final boolean dark = UIUtil.isUnderDarcula() && getScheme("Darcula") != null;
// It is reasonable to fetch attributes from Default color scheme. Otherwise if we launch IDE and then
// try switch from custom colors scheme (e.g. with dark background) to default one. Editor will show
// incorrect highlighting with "traces" of color scheme which was active during IDE startup.
final EditorColorsScheme defaultColorScheme = getScheme(dark ? "Darcula" : EditorColorsScheme.DEFAULT_SCHEME_NAME);
return defaultColorScheme.getAttributes(key);
}
private void extendDefaultScheme() {
@@ -0,0 +1,30 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.openapi.editor.colors.impl;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.editor.markup.TextAttributes;
/**
* @author Dennis.Ushakov
*/
public class TextAttributeKeyDefaultsProviderImpl implements TextAttributesKey.TextAttributeKeyDefaultsProvider {
@Override
public TextAttributes getDefaultAttributes(TextAttributesKey key) {
return ((EditorColorsManagerImpl)EditorColorsManager.getInstance()).getDefaultAttributes(key);
}
}
@@ -124,6 +124,11 @@ public final class RequestFocusInToolWindowCmd extends FinalizableCommand {
private void bringOwnerToFront() {
final Window owner = SwingUtilities.getWindowAncestor(myToolWindow.getComponent());
//Toolwindow component shouldn't take focus back if new dialog or frame appears
//Example: Ctrl+D on file history brings a diff dialog to front and then hides it by main frame by calling
// toFront on toolwindow window
Window activeFrame = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow();
if (activeFrame != null && activeFrame != owner) return;
//if (owner == null) {
// System.out.println("owner = " + owner);
// return;
@@ -131,7 +136,7 @@ public final class RequestFocusInToolWindowCmd extends FinalizableCommand {
// if owner is active window or it has active child window which isn't floating decorator then
// don't bring owner window to font. If we will make toFront every time then it's possible
// the following situation:
// 1. user prform refactoring
// 1. user perform refactoring
// 2. "Do not show preview" dialog is popping up.
// 3. At that time "preview" tool window is being activated and modal "don't show..." dialog
// isn't active.
@@ -132,6 +132,8 @@
<applicationService serviceInterface="com.intellij.openapi.editor.colors.ex.DefaultColorSchemesManager"
serviceImplementation="com.intellij.openapi.editor.colors.ex.DefaultColorSchemesManager"/>
<applicationService serviceInterface="com.intellij.openapi.editor.colors.TextAttributesKey$TextAttributeKeyDefaultsProvider"
serviceImplementation="com.intellij.openapi.editor.colors.impl.TextAttributeKeyDefaultsProviderImpl"/>
<applicationService serviceInterface="com.intellij.openapi.editor.colors.EditorColorsManager"
serviceImplementation="com.intellij.openapi.editor.colors.impl.EditorColorsManagerImpl"/>
<exportable serviceInterface="com.intellij.openapi.editor.colors.EditorColorsManager"/>
@@ -36,8 +36,8 @@ public class SelectFilePathsDialog extends AbstractSelectFilesDialog<FilePath> {
public SelectFilePathsDialog(final Project project, List<FilePath> originalFiles, final String prompt,
final VcsShowConfirmationOption confirmationOption,
@Nullable String okActionName, @Nullable String cancelActionName) {
super(project, false, confirmationOption, prompt, true);
@Nullable String okActionName, @Nullable String cancelActionName, boolean showDoNotAskOption) {
super(project, false, confirmationOption, prompt, showDoNotAskOption);
myFileList = new ChangesTreeList<FilePath>(project, originalFiles, true, true, null, null) {
protected DefaultTreeModel buildTreeModel(final List<FilePath> changes, ChangeNodeDecorator changeNodeDecorator) {
return new TreeModelBuilder(project, false).buildModelFromFilePaths(changes);
@@ -190,7 +190,7 @@ public class AbstractVcsHelperImpl extends AbstractVcsHelper {
}
final SelectFilePathsDialog dlg =
new SelectFilePathsDialog(myProject, files, prompt, confirmationOption, okActionName, cancelActionName);
new SelectFilePathsDialog(myProject, files, prompt, confirmationOption, okActionName, cancelActionName, true);
dlg.setTitle(title);
if (! confirmationOption.isPersistent()) {
dlg.setDoNotAskOption(null);
@@ -38,7 +38,6 @@ import org.jetbrains.jps.android.model.JpsAndroidSdkProperties;
import org.jetbrains.jps.builders.BuildOutputConsumer;
import org.jetbrains.jps.builders.BuildRootDescriptor;
import org.jetbrains.jps.builders.DirtyFilesHolder;
import org.jetbrains.jps.builders.FileProcessor;
import org.jetbrains.jps.cmdline.ClasspathBootstrap;
import org.jetbrains.jps.incremental.CompileContext;
import org.jetbrains.jps.incremental.ExternalProcessUtil;
@@ -77,19 +76,9 @@ public class AndroidDexBuilder extends TargetBuilder<BuildRootDescriptor, Androi
if (AndroidJpsUtil.isLightBuild(context)) {
return;
}
final boolean[] hasDirtyFiles = {false};
holder.processDirtyFiles(new FileProcessor<BuildRootDescriptor, AndroidDexBuildTarget>() {
@Override
public boolean apply(AndroidDexBuildTarget target, File file, BuildRootDescriptor root) throws IOException {
assert target == buildTarget;
hasDirtyFiles[0] = true;
return false;
}
});
try {
if (!doDexBuild(buildTarget, context, hasDirtyFiles[0])) {
if (!doDexBuild(buildTarget, context, holder.hasDirtyFiles())) {
throw new ProjectBuildException();
}
}
+1 -1
View File
@@ -51,7 +51,7 @@
bundle="org.jetbrains.idea.devkit.DevKitBundle"
groupKey="inspections.group.name" enabledByDefault="true" level="WARNING"
implementationClass="org.jetbrains.idea.devkit.inspections.UseGrayInspection"/>
<localInspection language="JAVA" shortName="InspectionUsingJBColors" displayName="Use Darcula aware JBColor"
<localInspection language="JAVA" shortName="UseJBColor" displayName="Use Darcula aware JBColor"
bundle="org.jetbrains.idea.devkit.DevKitBundle"
groupKey="inspections.group.name" enabledByDefault="true" level="WARNING"
implementationClass="org.jetbrains.idea.devkit.inspections.UseJBColorInspection"/>
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2012 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.
@@ -28,7 +28,7 @@ import com.intellij.ui.Gray;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.devkit.inspections.quickfix.ConvertToGayQuickFix;
import org.jetbrains.idea.devkit.inspections.quickfix.ConvertToGrayQuickFix;
/**
* @author Konstantin Bulenkov
@@ -75,7 +75,7 @@ public class UseGrayInspection extends DevKitInspectionBase {
int gg = Integer.parseInt(green.toString());
int bb = Integer.parseInt(blue.toString());
if (rr == gg && gg == bb && 0 <= rr && rr < 256) {
return manager.createProblemDescriptor(expression, "Convert to Gray._" + rr, new ConvertToGayQuickFix(rr), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly);
return manager.createProblemDescriptor(expression, "Convert to Gray._" + rr, new ConvertToGrayQuickFix(rr), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly);
}
} catch (Exception ignore){}
}
@@ -88,7 +88,7 @@ public class UseGrayInspection extends DevKitInspectionBase {
try {
int num = Integer.parseInt(literal.toString());
if (0 <= num && num < 256) {
return manager.createProblemDescriptor(expression, "Convert to Gray_" + num, new ConvertToGayQuickFix(num), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly);
return manager.createProblemDescriptor(expression, "Convert to Gray_" + num, new ConvertToGrayQuickFix(num), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, isOnTheFly);
}
} catch (Exception ignore){}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2012 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.
@@ -15,7 +15,7 @@
*/
package org.jetbrains.idea.devkit.inspections.quickfix;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.LocalQuickFixBase;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.JavaPsiFacade;
@@ -28,25 +28,14 @@ import org.jetbrains.annotations.NotNull;
/**
* @author Konstantin Bulenkov
*/
public class ConvertToGayQuickFix implements LocalQuickFix {
public class ConvertToGrayQuickFix extends LocalQuickFixBase {
private final int myNum;
public ConvertToGayQuickFix(int num) {
public ConvertToGrayQuickFix(int num) {
super("Convert to Gray._" + num, "Convert to Gray");
myNum = num;
}
@NotNull
@Override
public String getName() {
return "Convert to Gray._" + myNum;
}
@NotNull
@Override
public String getFamilyName() {
return "DevKit";
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
@@ -15,7 +15,7 @@
*/
package org.jetbrains.idea.devkit.inspections.quickfix;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.LocalQuickFixBase;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.JavaPsiFacade;
@@ -29,25 +29,14 @@ import org.jetbrains.annotations.NotNull;
/**
* @author Konstantin Bulenkov
*/
public class ConvertToJBColorConstantQuickFix implements LocalQuickFix {
public class ConvertToJBColorConstantQuickFix extends LocalQuickFixBase {
private final String myConstantName;
public ConvertToJBColorConstantQuickFix(String constantName) {
super("Convert to JBColor." + constantName, "Convert to JBColor");
myConstantName = constantName;
}
@NotNull
@Override
public String getName() {
return "Convert to JBColor." + myConstantName;
}
@NotNull
@Override
public String getFamilyName() {
return "Convert to JBColor";
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
@@ -15,7 +15,7 @@
*/
package org.jetbrains.idea.devkit.inspections.quickfix;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.LocalQuickFixBase;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
@@ -31,20 +31,9 @@ import org.jetbrains.annotations.NotNull;
/**
* @author Konstantin Bulenkov
*/
public class ConvertToJBColorQuickFix implements LocalQuickFix {
public class ConvertToJBColorQuickFix extends LocalQuickFixBase {
public ConvertToJBColorQuickFix() {
}
@NotNull
@Override
public String getName() {
return "Convert to JBColor";
}
@NotNull
@Override
public String getFamilyName() {
return getName();
super("Convert to JBColor");
}
@Override
@@ -15,10 +15,11 @@
*/
package git4idea.checkin;
import com.intellij.CommonBundle;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.CheckinProjectPanel;
@@ -26,6 +27,7 @@ import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.ObjectsConvertor;
import com.intellij.openapi.vcs.VcsException;
import com.intellij.openapi.vcs.changes.*;
import com.intellij.openapi.vcs.changes.ui.SelectFilePathsDialog;
import com.intellij.openapi.vcs.checkin.CheckinChangeListSpecificComponent;
import com.intellij.openapi.vcs.checkin.CheckinEnvironment;
import com.intellij.openapi.vcs.ui.RefreshableOnComponent;
@@ -182,10 +184,11 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
commit(myProject, root, files, messageFile, myNextCommitAuthor, myNextCommitAmend, myNextCommitAuthorDate);
}
catch (VcsException ex) {
if (!isMergeCommit(ex)) {
PartialOperation partialOperation = isMergeCommit(ex);
if (partialOperation == PartialOperation.NONE) {
throw ex;
}
if (!mergeCommit(myProject, root, added, removed, messageFile, myNextCommitAuthor, exceptions)) {
if (!mergeCommit(myProject, root, added, removed, messageFile, myNextCommitAuthor, exceptions, partialOperation)) {
throw ex;
}
}
@@ -223,6 +226,7 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
/**
* Preform a merge commit
*
*
* @param project a project
* @param root a vcs root
* @param added added files
@@ -230,6 +234,7 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
* @param messageFile a message file for commit
* @param author an author
* @param exceptions the list of exceptions to report
* @param partialOperation
* @return true if merge commit was successful
*/
private static boolean mergeCommit(final Project project,
@@ -238,7 +243,7 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
final Set<FilePath> removed,
final File messageFile,
final String author,
List<VcsException> exceptions) {
List<VcsException> exceptions, @NotNull final PartialOperation partialOperation) {
HashSet<FilePath> realAdded = new HashSet<FilePath>();
HashSet<FilePath> realRemoved = new HashSet<FilePath>();
// perform diff
@@ -278,26 +283,20 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
realAdded.removeAll(added);
realRemoved.removeAll(removed);
if (realAdded.size() != 0 || realRemoved.size() != 0) {
TreeSet<String> files = new TreeSet<String>();
for (FilePath f : realAdded) {
files.add(f.getPresentableUrl());
}
for (FilePath f : realRemoved) {
files.add(f.getPresentableUrl());
}
final StringBuilder fileList = new StringBuilder();
for (String f : files) {
//noinspection HardCodedStringLiteral
fileList.append("<li>");
fileList.append(StringUtil.escapeXml(f));
fileList.append("</li>");
}
final int[] rc = new int[1];
final List<FilePath> files = new ArrayList<FilePath>();
files.addAll(realAdded);
files.addAll(realRemoved);
final Ref<Boolean> mergeAll = new Ref<Boolean>();
try {
GuiUtils.runOrInvokeAndWait(new Runnable() {
public void run() {
rc[0] = Messages.showOkCancelDialog(project, GitBundle.message("commit.partial.merge.message", fileList.toString()),
GitBundle.getString("commit.partial.merge.title"), null);
String message = GitBundle.message("commit.partial.merge.message", partialOperation.getName());
SelectFilePathsDialog dialog = new SelectFilePathsDialog(project, files, message,
null, "Commit All Files", CommonBundle.getCancelButtonText(), false);
dialog.setTitle(GitBundle.getString("commit.partial.merge.title"));
dialog.show();
mergeAll.set(dialog.isOK());
}
});
}
@@ -307,7 +306,7 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
catch (Exception ex) {
throw new RuntimeException("Unable to invoke a message box on AWT thread", ex);
}
if (rc[0] != 0) {
if (!mergeAll.get()) {
return false;
}
// update non-indexed files
@@ -342,14 +341,21 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
}
/**
* Check if commit has failed due to unfinished merge
* Check if commit has failed due to unfinished merge or cherry-pick.
*
*
* @param ex an exception to examine
* @return true if exception means that there is a partial commit during merge
*/
private static boolean isMergeCommit(final VcsException ex) {
//noinspection HardCodedStringLiteral
return ex.getMessage().contains("fatal: cannot do a partial commit during a merge.");
private static PartialOperation isMergeCommit(final VcsException ex) {
String message = ex.getMessage();
if (message.contains("fatal: cannot do a partial commit during a merge")) {
return PartialOperation.MERGE;
}
if (message.contains("fatal: cannot do a partial commit during a cherry-pick")) {
return PartialOperation.CHERRY_PICK;
}
return PartialOperation.NONE;
}
/**
@@ -514,6 +520,22 @@ public class GitCheckinEnvironment implements CheckinEnvironment {
return rc;
}
private enum PartialOperation {
NONE("none"),
MERGE("merge"),
CHERRY_PICK("cherry-pick");
private final String myName;
PartialOperation(String name) {
myName = name;
}
String getName() {
return myName;
}
}
/**
* Sort changes by roots
*
@@ -22,11 +22,9 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.changes.*;
import com.intellij.openapi.vcs.checkin.CheckinEnvironment;
import com.intellij.openapi.vcs.history.VcsRevisionNumber;
import com.intellij.openapi.vcs.merge.MergeDialogCustomizer;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
import git4idea.GitPlatformFacade;
import git4idea.commands.Git;
@@ -195,7 +193,7 @@ public class GitCherryPicker {
private CherryPickData updateChangeListManager(@NotNull final GitCommit commit) {
final Collection<FilePath> paths = ChangesUtil.getPaths(commit.getChanges());
refreshChangedFiles(paths);
final String commitMessage = createCommitMessage(commit, paths);
final String commitMessage = createCommitMessage(commit);
LocalChangeList previouslyDefaultChangeList = myChangeListManager.getDefaultChangeList();
LocalChangeList changeList = createChangeListAfterUpdate(commit, paths, commitMessage);
return new CherryPickData(changeList, commitMessage, previouslyDefaultChangeList);
@@ -227,11 +225,19 @@ public class GitCherryPicker {
}
@NotNull
private String createCommitMessage(@NotNull GitCommit commit, @NotNull Collection<FilePath> paths) {
CheckinEnvironment ce = myPlatformFacade.getVcs(myProject).getCheckinEnvironment();
String message = ce == null ? null : ce.getDefaultMessageFor(ArrayUtil.toObjectArray(paths, FilePath.class));
message = message == null ? commit.getDescription() + "\n(cherry-picked from " + commit.getShortHash().getString() + ")" : message;
return message;
private static String createCommitMessage(@NotNull GitCommit commit) {
// make sure there is an empty line after description
String spaces;
if (commit.getDescription().endsWith("\n\n")) {
spaces = "";
}
else if (commit.getDescription().endsWith("\n")) {
spaces = "\n";
}
else {
spaces = "\n\n";
}
return commit.getDescription() + spaces + "(cherry-picked from " + commit.getShortHash().getString() + ")";
}
private boolean showCommitDialogAndWaitForCommit(@NotNull final GitRepository repository, @NotNull final GitCommitWrapper commit,
@@ -62,7 +62,9 @@ commit.author.tooltip=<html>Specify a commit author here if it is different from
commit.author=&Author:
commit.amend.tooltip=<html>Merge this commit with the previous one</html>
commit.amend=Amend commit
commit.partial.merge.message=<html>The following files are not included in commit.<ul>{0}</ul>Perform commit with all files included?</html>
commit.partial.merge.message=Partial commit during a {0} is not allowed.\n\
The following files are not included in commit.\n\
Perform commit with all files included?
commit.partial.merge.title=Partial Merge Commit
commit.push.changes.tooltip=When this option is enabled, changes are pushed to the server after commit.
commit.push.changes=&Push Changes
@@ -23,6 +23,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.ListCellRendererWrapper;
import git4idea.GitBranch;
import git4idea.GitRemoteBranch;
import git4idea.GitUtil;
import git4idea.commands.GitCommand;
import git4idea.commands.GitLineHandler;
@@ -38,7 +39,9 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
/**
@@ -221,7 +224,9 @@ public class GitPullDialog extends DialogWrapper {
GitBranchTrackInfo trackInfo = GitUtil.getTrackInfoForCurrentBranch(repository);
String currentRemoteBranch = trackInfo == null ? null : trackInfo.getRemoteBranch().getNameForLocalOperations();
for (GitBranch remoteBranch : repository.getBranches().getRemoteBranches()) {
List<GitRemoteBranch> remoteBranches = new ArrayList<GitRemoteBranch>(repository.getBranches().getRemoteBranches());
Collections.sort(remoteBranches);
for (GitBranch remoteBranch : remoteBranches) {
if (belongsToRemote(remoteBranch, selectedRemote)) {
myBranchChooser.addElement(remoteBranch.getName(), remoteBranch.getName().equals(currentRemoteBranch));
}
@@ -338,4 +338,5 @@ java.style.for.each.statement.requires.a.type.declaration=Java-style for-each st
enums.may.not.have.extends.clause=Enums may not have 'extends' clause
super.cannot.be.used.in.static.context='super' cannot be used in static context
qualified.0.is.allowed.only.in.nested.or.inner.classes=Qualified {0} is allowed only in nested/inner classes
groovy.file.0=Groovy file ''{0}''
groovy.file.0=Groovy file ''{0}''
type.argument.list.is.not.allowed.here=Type argument list is not allowed here
@@ -149,19 +149,16 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
@Override
public void visitTypeArgumentList(GrTypeArgumentList typeArgumentList) {
PsiElement parent = typeArgumentList.getParent();
final PsiElement resolved;
if (parent instanceof GrReferenceElement) {
resolved = ((GrReferenceElement)parent).resolve();
}
else {
resolved = null;
}
if (!(parent instanceof GrReferenceElement)) return;
final GroovyResolveResult resolveResult = ((GrReferenceElement)parent).advancedResolve();
final PsiElement resolved = resolveResult.getElement();
final PsiSubstitutor substitutor = resolveResult.getSubstitutor();
if (resolved == null) return;
if (!(resolved instanceof PsiTypeParameterListOwner)) {
//myHolder.createErrorAnnotation(typeArgumentList, GroovyBundle.message("type.argument.list.is.no.a"))
//todo correct error description
myHolder.createWarningAnnotation(typeArgumentList, GroovyBundle.message("type.argument.list.is.not.allowed.here"));
return;
}
@@ -173,8 +170,8 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
final GrTypeElement[] arguments = typeArgumentList.getTypeArgumentElements();
if (arguments.length != parameters.length) {
myHolder.createErrorAnnotation(typeArgumentList,
GroovyBundle.message("wrong.number.of.type.arguments", arguments.length, parameters.length));
myHolder.createWarningAnnotation(typeArgumentList,
GroovyBundle.message("wrong.number.of.type.arguments", arguments.length, parameters.length));
return;
}
@@ -183,8 +180,9 @@ public class GroovyAnnotator extends GroovyElementVisitor implements Annotator {
final PsiClassType[] superTypes = parameter.getExtendsListTypes();
final PsiType argType = arguments[i].getType();
for (PsiClassType superType : superTypes) {
if (!superType.isAssignableFrom(argType)) {
myHolder.createErrorAnnotation(arguments[i], GroovyBundle
final PsiType substitutedSuper = substitutor.substitute(superType);
if (substitutedSuper != null && !substitutedSuper.isAssignableFrom(argType)) {
myHolder.createWarningAnnotation(arguments[i], GroovyBundle
.message("type.argument.0.is.not.in.its.bound.should.extend.1", argType.getCanonicalText(), superType.getCanonicalText()));
break;
}
@@ -75,6 +75,17 @@ package java.math;
public class BigDecimal extends Number implements Comparable<BigDecimal> {
}
''')
}
protected void addHashSet() {
myFixture.addClass('''\
package java.util;
public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable
{}
''')
}
@@ -408,9 +408,9 @@ private def handleImplicitBind(arg) {
public void testIncorrectTypeArguments() {
myFixture.configureByText('_.groovy', '''\
class C <T extends String> {}
C<<error descr="Type parameter 'java.lang.Double' is not in its bound; should extend 'java.lang.String'">Double</error>> c
C<<warning descr="Type parameter 'java.lang.Double' is not in its bound; should extend 'java.lang.String'">Double</warning>> c
C<String> c2
C<error descr="Wrong number of type arguments: 2; required: 1"><String, Double></error> c3
C<warning descr="Wrong number of type arguments: 2; required: 1"><String, Double></warning> c3
''')
myFixture.testHighlighting(true, false, true)
}
@@ -953,6 +953,25 @@ print new Foo()
<error descr="Ambiguous code block">{
String toString() {'abc'}
}</error>
''')
}
void testGenerics() {
addHashSet()
testHighlighting('''
class NodeInfo{}
interface NodeEvent<T> {}
interface TrackerEventsListener<N extends NodeInfo, E extends NodeEvent<N>> {
void onEvents(Collection<E> events)
}
class AgentInfo extends NodeInfo {}
print new HashSet<TrackerEventsListener<AgentInfo, NodeEvent<AgentInfo>>>() //correct
print new HashSet<TrackerEventsListener<AgentInfo, <warning descr="Type parameter 'NodeEvent<java.lang.Object>' is not in its bound; should extend 'NodeEvent<N>'">NodeEvent<Object></warning>>>() //incorrect
''')
}
}
@@ -28,10 +28,10 @@ class TroubleCase {
}
public interface Foo<FFIC> {}
public class Bar implements Cloneable, Zoo<Goo, Doo, <error descr="Type parameter 'Coo' is not in its bound; should extend 'Hoo<AR>'">Coo</error>, <error descr="Type parameter 'Woo' is not in its bound; should extend 'Hoo<FR>'">Woo</error>> {}
public class Bar implements Cloneable, Zoo<Goo, Doo, Coo, Woo> {}
public interface Zoo<AR, FR, AM extends Hoo<AR>, FM extends Hoo<FR>> {}
public interface Hoo<R> {}
public class Baz implements Cloneable, Zoo<String,String,<error descr="Type parameter 'Too' is not in its bound; should extend 'Hoo<AR>'">Too</error>,<error descr="Type parameter 'Yoo' is not in its bound; should extend 'Hoo<FR>'">Yoo</error>> {}
public class Baz implements Cloneable, Zoo<String,String,Too,Yoo> {}
public class Goo {}
public class Too implements Hoo<String> {}
public class Coo implements Serializable, Cloneable, Hoo<Goo> {}
@@ -23,12 +23,13 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
@@ -49,8 +50,9 @@ import org.jetbrains.idea.maven.model.MavenResource;
import org.jetbrains.idea.maven.project.MavenProject;
import org.jetbrains.idea.maven.project.MavenProjectsManager;
import org.jetbrains.idea.maven.utils.MavenLog;
import org.jetbrains.idea.maven.vfs.MavenPropertiesVirtualFileSystem;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
@@ -58,6 +60,8 @@ import java.util.regex.Pattern;
public class MavenDomUtil {
private static final Key<Pair<Long, Set<VirtualFile>>> FILTERED_RESOURCES_ROOTS_KEY = Key.create("MavenDomUtil.FILTERED_RESOURCES_ROOTS");
// see http://maven.apache.org/settings.html
private static final Set<String> SUBTAGS_IN_SETTINGS_FILE = ContainerUtil.newHashSet("localRepository", "interactiveMode",
"usePluginRegistry", "offline", "pluginGroups",
@@ -317,21 +321,54 @@ public class MavenDomUtil {
return prop == null ? null : prop.getPsiElement().getFirstChild().getNextSibling().getNextSibling();
}
public static boolean isFilteredResourceFile(PsiElement element) {
MavenProject project = findContainingProject(element);
if (project == null) return false;
private static Set<VirtualFile> getFilteredResourcesRoots(@NotNull MavenProject mavenProject) {
Pair<Long, Set<VirtualFile>> cachedValue = mavenProject.getCachedValue(FILTERED_RESOURCES_ROOTS_KEY);
VirtualFile file = MavenDomUtil.getVirtualFile(element);
if (cachedValue == null || cachedValue.first != VirtualFileManager.getInstance().getModificationCount()) {
Set<VirtualFile> set = null;
for (MavenResource resource : mavenProject.getResources()) {
if (!resource.isFiltered()) continue;
VirtualFile resourceDir = LocalFileSystem.getInstance().findFileByPath(resource.getDirectory());
if (resourceDir == null) continue;
if (set == null) {
set = new HashSet<VirtualFile>();
}
set.add(resourceDir);
}
if (set == null) {
set = Collections.emptySet();
}
cachedValue = Pair.create(VirtualFileManager.getInstance().getModificationCount(), set);
mavenProject.putCachedValue(FILTERED_RESOURCES_ROOTS_KEY, cachedValue);
}
return cachedValue.second;
}
public static boolean isFilteredResourceFile(PsiElement element) {
VirtualFile file = getVirtualFile(element);
if (file == null) return false;
for (MavenResource each : project.getResources()) {
if (!each.isFiltered()) continue;
MavenProjectsManager manager = MavenProjectsManager.getInstance(element.getProject());
MavenProject mavenProject = manager.findContainingProject(file);
if (mavenProject == null) return false;
VirtualFile resourceDir = LocalFileSystem.getInstance().findFileByPath(each.getDirectory());
if (resourceDir == null) continue;
if (!VfsUtil.isAncestor(resourceDir, file, true)) continue;
return true;
Set<VirtualFile> filteredRoots = getFilteredResourcesRoots(mavenProject);
if (!filteredRoots.isEmpty()) {
for (VirtualFile f = file.getParent(); f != null; f = f.getParent()) {
if (filteredRoots.contains(f)) {
return true;
}
}
}
return false;
}
@@ -87,16 +87,17 @@ public class SwitchTaskCombo extends ComboBoxAction implements DumbAware {
presentation.setIcon(null);
}
else {
LocalTask activeTask = TaskManager.getManager(project).getActiveTask();
TaskManager taskManager = TaskManager.getManager(project);
LocalTask activeTask = taskManager.getActiveTask();
presentation.setVisible(true);
presentation.setEnabled(true);
if (isImplicit(activeTask) && !TaskSettings.getInstance().ALWAYS_DISPLAY_COMBO) {
presentation.setText("");
presentation.setIcon(null);
presentation.setDescription("Switch Tasks");
if (isImplicit(activeTask) &&
taskManager.getAllRepositories().length == 0 &&
!TaskSettings.getInstance().ALWAYS_DISPLAY_COMBO) {
presentation.setVisible(false);
} else {
}
else {
String s = getText(activeTask);
presentation.setText(s);
presentation.setIcon(activeTask.getIcon());