Merge remote-tracking branch 'origin/master'

This commit is contained in:
irengrig
2015-03-25 16:22:52 +01:00
106 changed files with 6818 additions and 869 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -173,15 +173,14 @@ public class JavaStackFrame extends XStackFrame {
}
final Location location = myDescriptor.getLocation();
LOG.assertTrue(location != null);
final ObjectReference thisObjectReference = myDescriptor.getThisObject();
if (thisObjectReference != null) {
ValueDescriptorImpl thisDescriptor = myNodeManager.getThisDescriptor(null, thisObjectReference);
children.add(JavaValue.create(thisDescriptor, evaluationContext, myNodeManager));
}
else {
StaticDescriptorImpl staticDecriptor = myNodeManager.getStaticDescriptor(myDescriptor, location.method().declaringType());
else if (location != null) {
StaticDescriptorImpl staticDecriptor = myNodeManager.getStaticDescriptor(myDescriptor, location.declaringType());
if (staticDecriptor.isExpandable()) {
children.addTopGroup(new JavaStaticGroup(staticDecriptor, evaluationContext, myNodeManager));
}
@@ -214,7 +213,8 @@ public class JavaStackFrame extends XStackFrame {
if (classRenderer.SHOW_VAL_FIELDS_AS_LOCAL_VARIABLES) {
if (thisObjectReference != null && debugProcess.getVirtualMachineProxy().canGetSyntheticAttribute()) {
final ReferenceType thisRefType = thisObjectReference.referenceType();
if (thisRefType instanceof ClassType && thisRefType.equals(location.declaringType()) && thisRefType.name().contains("$")) { // makes sense for nested classes only
if (thisRefType instanceof ClassType && location != null
&& thisRefType.equals(location.declaringType()) && thisRefType.name().contains("$")) { // makes sense for nested classes only
final ClassType clsType = (ClassType)thisRefType;
for (Field field : clsType.fields()) {
if (DebuggerUtils.isSynthetic(field) && StringUtil.startsWith(field.name(), FieldDescriptorImpl.OUTER_LOCAL_VAR_FIELD_PREFIX)) {
@@ -281,6 +281,7 @@ public class StackFrameDescriptorImpl extends NodeDescriptorImpl implements Stac
return myIsInLibraryContent;
}
@Nullable
public Location getLocation() {
return myLocation;
}
@@ -147,10 +147,7 @@ public class SdkSettingsStep extends ModuleWizardStep {
myWizardContext.setProjectJdk(jdk);
}
else {
Sdk sdk = ProjectRootManager.getInstance(project).getProjectSdk();
if (sdk == null || !myModuleBuilder.isSuitableSdkType(sdk.getSdkType())) {
myModuleBuilder.setModuleJdk(myJdkComboBox.getSelectedJdk());
} // else, inherit project jdk
myModuleBuilder.setModuleJdk(myJdkComboBox.getSelectedJdk());
}
}
@@ -575,7 +575,7 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
}
final PsiSubstitutor inferredSubstitutor = TypeConversionUtil.getClassSubstitutor(superClass, classCandidate, classResolveResult.getSubstitutor());
final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, myAnonymClass.getBaseClassType());
if (inferredSubstitutor == null ||
if (inferredSubstitutor != null &&
!Comparing.equal(inferredSubstitutor.substitute(paramType), substitutor.substitute(paramType))) {
myBodyContainsForbiddenRefs = true;
return;
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -30,6 +30,7 @@ import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.testFramework.builders.JavaModuleFixtureBuilder;
@@ -142,6 +143,7 @@ abstract class JavaModuleFixtureBuilderImpl<T extends ModuleFixture> extends Mod
final Sdk jdk;
if (myJdk != null) {
VfsRootAccess.allowRootAccessTemporarily(module, myJdk);
jdk = JavaSdk.getInstance().createJdk(module.getName() + "_jdk", myJdk, false);
((ProjectJdkImpl)jdk).setVersionString("java 1.5");
}
@@ -37,6 +37,9 @@ public class MockPackageFacadeBuilderService extends BuilderService {
catch (ClassNotFoundException e) {
return Collections.emptyList();
}
catch (NoClassDefFoundError e) {
return Collections.emptyList();
}
catch (Exception e) {
throw new RuntimeException(e);
}
@@ -328,4 +328,27 @@ public class IncrementalArtifactBuildingTest extends ArtifactBuilderTestCase {
assertOutput(a2, fs().file("a.txt", "2"));
}
//todo[nik] fix
//ZD-51993
public void _testFilesCopiedToTwoDifferentPlacesInArtifact() {
final String fileA = createFile("res/a.txt", "0");
final String fileB = createFile("res/b.txt", "0");
String dir = PathUtil.getParentPath(fileA);
JpsArtifact a = addArtifact("a", root()
.dir("d").dirCopy(dir).end()
.archive("a.zip").dirCopy(dir));
buildAll();
change(fileA, "1");
buildAll();
assertOutput(a, fs()
.dir("d").file("a.txt", "1").file("b.txt", "0").end()
.archive("a.zip").file("a.txt", "1").file("b.txt", "0"));
change(fileB, "1");
buildAll();
assertOutput(a, fs()
.dir("d").file("a.txt", "1").file("b.txt", "1").end()
.archive("a.zip").file("a.txt", "1").file("b.txt", "1"));
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -26,6 +26,8 @@ import com.intellij.util.EventDispatcher;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
public abstract class DeprecatedVirtualFileSystem extends VirtualFileSystem {
private final EventDispatcher<VirtualFileListener> myEventDispatcher = EventDispatcher.create(VirtualFileListener.class);
@@ -135,4 +137,39 @@ public abstract class DeprecatedVirtualFileSystem extends VirtualFileSystem {
public boolean isReadOnly() {
return true;
}
@Override
protected void deleteFile(Object requestor, @NotNull VirtualFile vFile) throws IOException {
throw new UnsupportedOperationException("deleteFile() not supported");
}
@Override
protected void moveFile(Object requestor, @NotNull VirtualFile vFile, @NotNull VirtualFile newParent) throws IOException {
throw new UnsupportedOperationException("move() not supported");
}
@Override
protected void renameFile(Object requestor, @NotNull VirtualFile vFile, @NotNull String newName) throws IOException {
throw new UnsupportedOperationException("renameFile() not supported");
}
@NotNull
@Override
public VirtualFile createChildFile(Object requestor, @NotNull VirtualFile vDir, @NotNull String fileName) throws IOException {
throw new UnsupportedOperationException("createChildFile() not supported");
}
@NotNull
@Override
public VirtualFile createChildDirectory(Object requestor, @NotNull VirtualFile vDir, @NotNull String dirName) throws IOException {
throw new UnsupportedOperationException("createChildDirectory() not supported");
}
@NotNull
@Override
public VirtualFile copyFile(Object requestor,
@NotNull VirtualFile virtualFile,
@NotNull VirtualFile newParent,
@NotNull String copyName) throws IOException {
throw new UnsupportedOperationException("copyFile() not supported");
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -84,39 +84,6 @@ public abstract class LightVirtualFileBase extends VirtualFile {
public VirtualFile refreshAndFindFileByPath(@NotNull String path) {
return null;
}
@Override
public void deleteFile(Object requestor, @NotNull VirtualFile vFile) throws IOException {
}
@Override
public void moveFile(Object requestor, @NotNull VirtualFile vFile, @NotNull VirtualFile newParent) throws IOException {
}
@NotNull
@Override
public VirtualFile copyFile(Object requestor,
@NotNull VirtualFile vFile,
@NotNull VirtualFile newParent,
@NotNull final String copyName) throws IOException {
throw new IOException("Cannot copy files");
}
@Override
public void renameFile(Object requestor, @NotNull VirtualFile vFile, @NotNull String newName) throws IOException {
}
@NotNull
@Override
public VirtualFile createChildFile(Object requestor, @NotNull VirtualFile vDir, @NotNull String fileName) throws IOException {
throw new IOException("Cannot create files");
}
@Override
@NotNull
public VirtualFile createChildDirectory(Object requestor, @NotNull VirtualFile vDir, @NotNull String dirName) throws IOException {
throw new IOException("Cannot create directories");
}
}
private static final MyVirtualFileSystem ourFileSystem = new MyVirtualFileSystem();
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -22,7 +22,6 @@ import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@@ -72,40 +71,4 @@ public class CoreJarFileSystem extends DeprecatedVirtualFileSystem {
public VirtualFile refreshAndFindFileByPath(@NotNull String path) {
return findFileByPath(path);
}
@Override
protected void deleteFile(Object requestor, @NotNull VirtualFile vFile) throws IOException {
throw new UnsupportedOperationException("JarFileSystem is read-only");
}
@Override
protected void moveFile(Object requestor, @NotNull VirtualFile vFile, @NotNull VirtualFile newParent) throws IOException {
throw new UnsupportedOperationException("JarFileSystem is read-only");
}
@Override
protected void renameFile(Object requestor, @NotNull VirtualFile vFile, @NotNull String newName) throws IOException {
throw new UnsupportedOperationException("JarFileSystem is read-only");
}
@NotNull
@Override
protected VirtualFile createChildFile(Object requestor, @NotNull VirtualFile vDir, @NotNull String fileName) throws IOException {
throw new UnsupportedOperationException("JarFileSystem is read-only");
}
@NotNull
@Override
protected VirtualFile createChildDirectory(Object requestor, @NotNull VirtualFile vDir, @NotNull String dirName) throws IOException {
throw new UnsupportedOperationException("JarFileSystem is read-only");
}
@NotNull
@Override
protected VirtualFile copyFile(Object requestor,
@NotNull VirtualFile virtualFile,
@NotNull VirtualFile newParent,
@NotNull String copyName) throws IOException {
throw new UnsupportedOperationException("JarFileSystem is read-only");
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -23,7 +23,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
/**
* @author yole
@@ -53,45 +52,4 @@ public class CoreLocalFileSystem extends DeprecatedVirtualFileSystem {
public VirtualFile refreshAndFindFileByPath(@NotNull String path) {
return findFileByPath(path);
}
@Override
protected void deleteFile(Object requestor, @NotNull VirtualFile vFile) throws IOException {
throw new UnsupportedOperationException("deleteFile() not supported");
}
@Override
protected void moveFile(Object requestor, @NotNull VirtualFile vFile, @NotNull VirtualFile newParent) throws IOException {
throw new UnsupportedOperationException("move() not supported");
}
@Override
protected void renameFile(Object requestor, @NotNull VirtualFile vFile, @NotNull String newName) throws IOException {
throw new UnsupportedOperationException("renameFile() not supported");
}
@NotNull
@Override
protected VirtualFile createChildFile(Object requestor, @NotNull VirtualFile vDir, @NotNull String fileName) throws IOException {
throw new UnsupportedOperationException("createChildFile() not supported");
}
@NotNull
@Override
protected VirtualFile createChildDirectory(Object requestor, @NotNull VirtualFile vDir, @NotNull String dirName) throws IOException {
throw new UnsupportedOperationException("createChildDirectory() not supported");
}
@NotNull
@Override
protected VirtualFile copyFile(Object requestor,
@NotNull VirtualFile virtualFile,
@NotNull VirtualFile newParent,
@NotNull String copyName) throws IOException {
throw new UnsupportedOperationException("copyFile() not supported");
}
@Override
public boolean isReadOnly() {
return true;
}
}
@@ -46,6 +46,9 @@ public abstract class DiffContentFactory {
@NotNull
public abstract DocumentContent create(@NotNull String text, @Nullable FileType type);
@NotNull
public abstract DocumentContent create(@NotNull String text, @Nullable FileType type, boolean respectLineSeparators);
@NotNull
public abstract DocumentContent create(@Nullable Project project, @NotNull Document document);
@@ -65,7 +68,7 @@ public abstract class DiffContentFactory {
* @param referenceContent used to detect FileType and proper highlighting for clipboard content
*/
@NotNull
public abstract DocumentContent createClipboardContent(@NotNull DocumentContent referenceContent);
public abstract DocumentContent createClipboardContent(@Nullable DocumentContent referenceContent);
@NotNull
public abstract DiffContent createBinary(@Nullable Project project,
@@ -30,6 +30,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.BinaryLightVirtualFile;
import com.intellij.util.LineSeparator;
import com.intellij.util.PathUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -37,6 +38,7 @@ import org.jetbrains.annotations.Nullable;
import java.awt.datatransfer.DataFlavor;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
public class DiffContentFactoryImpl extends DiffContentFactory {
public final Logger LOG = Logger.getInstance(DiffContentFactoryImpl.class);
@@ -56,9 +58,13 @@ public class DiffContentFactoryImpl extends DiffContentFactory {
@Override
@NotNull
public DocumentContent create(@NotNull String text, @Nullable FileType type) {
Document document = EditorFactory.getInstance().createDocument(StringUtil.convertLineSeparators(text));
document.setReadOnly(true);
return new DocumentContentImpl(document, type, null, null, null);
return create(text, type, true);
}
@Override
@NotNull
public DocumentContent create(@NotNull String text, @Nullable FileType type, boolean respectLineSeparators) {
return createImpl(text, type, null, null, respectLineSeparators, true);
}
@Override
@@ -102,17 +108,32 @@ public class DiffContentFactoryImpl extends DiffContentFactory {
@Override
@NotNull
public DiffContent createClipboardContent() {
String text = CopyPasteManager.getInstance().getContents(DataFlavor.stringFlavor);
Document document = EditorFactory.getInstance().createDocument(StringUtil.convertLineSeparators(StringUtil.notNullize(text)));
return new DocumentContentImpl(document); // TODO: show difference in line separators ?
return createClipboardContent(null);
}
@Override
@NotNull
public DocumentContent createClipboardContent(@NotNull DocumentContent mainContent) {
public DocumentContent createClipboardContent(@Nullable DocumentContent mainContent) {
String text = CopyPasteManager.getInstance().getContents(DataFlavor.stringFlavor);
Document document = EditorFactory.getInstance().createDocument(StringUtil.convertLineSeparators(StringUtil.notNullize(text)));
return new DocumentContentWrapper(document, mainContent);
FileType type = mainContent != null ? mainContent.getContentType() : null;
VirtualFile highlightFile = mainContent != null ? mainContent.getHighlightFile() : null;
return createImpl(StringUtil.notNullize(text), type, highlightFile, null, true, false);
}
@NotNull
private static DocumentContent createImpl(@NotNull String text,
@Nullable FileType type,
@Nullable VirtualFile highlightFile,
@Nullable Charset charset,
boolean respectLineSeparators,
boolean readOnly) {
// TODO: detect invalid (different across the file) separators ?
LineSeparator separator = respectLineSeparators ? StringUtil.detectSeparators(text) : null;
Document document = EditorFactory.getInstance().createDocument(StringUtil.convertLineSeparators(text));
if (readOnly) document.setReadOnly(true);
return new DocumentContentImpl(document, type, highlightFile, separator, charset);
}
@Override
@@ -25,6 +25,8 @@ import org.jetbrains.annotations.Nullable;
import java.nio.charset.Charset;
@Deprecated
/** @deprecated (to be removed in IDEA 15) */
public class DocumentContentWrapper implements DocumentContent {
@NotNull private final DocumentContent myBase;
@NotNull private final Document myDocument;
@@ -312,11 +312,13 @@ public class SimpleDiffChange {
boolean isEditable = DiffUtil.isEditable(mySide.select(myEditor1, myEditor2));
boolean isOtherEditable = DiffUtil.isEditable(mySide.other().select(myEditor1, myEditor2));
boolean isAppendable = myFragment.getStartLine1() != myFragment.getEndLine1() &&
myFragment.getStartLine2() != myFragment.getEndLine2();
if ((myShiftPressed || !isOtherEditable) && isEditable) {
return createRevertRenderer(mySide);
}
if (myCtrlPressed) {
if (myCtrlPressed && isAppendable) {
return createAppendRenderer(mySide);
}
return createApplyRenderer(mySide);
@@ -291,7 +291,6 @@ public class UISettings extends SimpleModificationTracker implements PersistentS
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
}
}
UIUtil.setHintingForLCDText(g2d);
}
/**
@@ -0,0 +1,42 @@
/*
* Copyright 2000-2015 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.externalSystem.service.execution;
import com.intellij.openapi.externalSystem.model.ExternalSystemException;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Vladislav.Soroka
* @since 12/12/2014
*/
public class NotSupportedException extends ExternalSystemException {
public NotSupportedException(@Nullable String message) {
super(message);
}
public NotSupportedException(@Nullable Throwable cause) {
super(cause);
}
public NotSupportedException(@Nullable String message, @NotNull String... quickFixes) {
super(message, quickFixes);
}
public NotSupportedException(@Nullable String message, @Nullable Throwable cause, @NotNull String... quickFixes) {
super(message, cause, quickFixes);
}
}
@@ -6,7 +6,8 @@ import com.intellij.openapi.externalSystem.model.ProjectSystemId;
import com.intellij.openapi.externalSystem.model.task.*;
import com.intellij.openapi.externalSystem.service.ExternalSystemFacadeManager;
import com.intellij.openapi.externalSystem.service.RemoteExternalSystemFacade;
import com.intellij.openapi.externalSystem.service.notification.ExternalSystemProgressNotificationManager;
import com.intellij.openapi.externalSystem.service.execution.NotSupportedException;
import com.intellij.openapi.externalSystem.service.notification.*;
import com.intellij.openapi.externalSystem.util.ExternalSystemBundle;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.project.Project;
@@ -190,6 +191,12 @@ public abstract class AbstractExternalSystemTask implements ExternalSystemTask {
setState(result ? ExternalSystemTaskState.CANCELED : ExternalSystemTaskState.CANCELLATION_FAILED);
return result;
}
catch (NotSupportedException e) {
NotificationData notification =
new NotificationData("Cancellation failed", e.getMessage(), NotificationCategory.WARNING, NotificationSource.PROJECT_SYNC);
notification.setBalloonNotification(true);
ExternalSystemNotificationManager.getInstance(getIdeProject()).showNotification(getExternalSystemId(), notification);
}
catch (Throwable e) {
setState(ExternalSystemTaskState.CANCELLATION_FAILED);
myError.set(e);
@@ -100,10 +100,14 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
public static final Key<ConsoleViewImpl> CONSOLE_VIEW_IN_EDITOR_VIEW = Key.create("CONSOLE_VIEW_IN_EDITOR_VIEW");
static {
private static boolean ourTypedHandlerInitialized;
private static synchronized void initTypedHandler() {
if (ourTypedHandlerInitialized) return;
final EditorActionManager actionManager = EditorActionManager.getInstance();
final TypedAction typedAction = actionManager.getTypedAction();
typedAction.setupHandler(new MyTypedHandler(typedAction.getHandler()));
ourTypedHandlerInitialized = true;
}
@@ -281,6 +285,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
boolean usePredefinedMessageFilter)
{
super(new BorderLayout());
initTypedHandler();
myIsViewer = viewer;
myState = initialState;
myPsiDisposedCheck = new DisposedPsiManagerCheck(project);
@@ -157,7 +157,9 @@ public class ClasspathStorage extends StateStorageBase<ClasspathStorage.MyStorag
public void analyzeExternalChangesAndUpdateIfNeed(@NotNull Collection<VirtualFile> changedFiles, @NotNull Set<String> componentNames) {
// if some file changed, so, changed
componentNames.add("NewModuleRootManager");
myStorageData.loaded = false;
if (myStorageData != null) {
myStorageData.loaded = false;
}
}
@Nullable
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -42,7 +42,7 @@ public abstract class JarFileSystem extends ArchiveFileSystem implements JarCopy
}
/** @deprecated to be removed in IDEA 15 */
@SuppressWarnings({"UnusedDeclaration", "deprecation"})
@SuppressWarnings("deprecation")
public abstract JarFile getJarFile(@NotNull VirtualFile entryVFile) throws IOException;
@Nullable
@@ -0,0 +1,141 @@
/*
* Copyright 2000-2015 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.internal.validation;
import com.intellij.CommonBundle;
import com.intellij.ide.impl.ProjectNewWindowDoNotAskOption;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.ui.Messages;
import javax.swing.*;
/**
* @author Denis Fokin
*/
public class CheckMessagesButtonsOrderAction extends AnAction implements DumbAware {
@Override
public void actionPerformed(AnActionEvent e) {
new Thread() {
@Override
public void run() {
super.run();
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
// Case 1
Messages.showDialog("unchecked unfocused checkbox, [Proceed], ____,Cancel, *Show ussages*",
"Message 1", new String [] {"Show usages", "Cancel", "Proceed"}, 0, 0,
Messages.getQuestionIcon(), new ProjectNewWindowDoNotAskOption());
// Case 2
Messages.showDialog("unchecked unfocused checkbox, [Proceed], ____,Cancel, *Show ussages*",
"Message 2", new String [] {"Show usages", "Cancel", "Proceed"}, 0, 1,
Messages.getQuestionIcon(), new ProjectNewWindowDoNotAskOption());
// Case 3
Messages.showDialog("unchecked unfocused checkbox, [Proceed], ____, *Cancel*, Show ussages",
"Message 3", new String [] {"Show usages", "Cancel", "Proceed"}, 1, 0,
Messages.getQuestionIcon(), new ProjectNewWindowDoNotAskOption());
// Case 4
Messages.showDialog("unchecked unfocused checkbox, [Proceed], ____, *Cancel*, Show ussages",
"Message 4", new String [] {"Show usages", "Cancel", "Proceed"}, 1, 1,
Messages.getQuestionIcon(), new ProjectNewWindowDoNotAskOption());
// Case 5
Messages.showDialog("[Proceed], ____, Cancel, *Show ussages*",
"Message 5", new String [] {"Show usages", "Cancel", "Proceed"}, 0, 1,
Messages.getQuestionIcon(), null);
// Case 6
Messages.showYesNoCancelDialog("unchecked unfocused checkbox, [New Window], ____, Cancel, *This Window*",
"Message 6",
"This window",
"New Window",
CommonBundle.getCancelButtonText(),
Messages.getQuestionIcon(),
new ProjectNewWindowDoNotAskOption());
// Case 7
Messages.showDialog("[Variant 1], Variant 2, Variant 3, Cancel, *Ok*",
"Message 7",
new String[]{"Ok", "Cancel", "Variant 3", "Variant 2", "Variant 1"},
0, 1, Messages.getQuestionIcon(), null);
// Case 8
Messages.showDialog( "unchecked unfocused checkbox, [Variant 1], Variant 2, Variant 3, Cancel, *Ok*",
"Message 8",
new String [] {"Ok", "Cancel", "Variant 3", "Variant 2", "Variant 1"},
0, 0, Messages.getQuestionIcon(), new ProjectNewWindowDoNotAskOption());
// Case 9
Messages.showDialog( "unchecked unfocused checkbox, [Variant 1], Variant 2, Variant 3, *Cancel*, Ok",
"Message 9",
new String [] {"Ok", "Cancel", "Variant 3", "Variant 2", "Variant 1"},
1, 1, Messages.getQuestionIcon(), new ProjectNewWindowDoNotAskOption());
// Case 10
Messages.showDialog( "unchecked unfocused checkbox, [Variant 1], Variant 2, Variant 3, Cancel, *Ok*",
"Message 10",
new String [] {"Ok", "Cancel", "Variant 3", "Variant 2", "Variant 1"},
0, 1, Messages.getQuestionIcon(), new ProjectNewWindowDoNotAskOption());
// Case 11
Messages.showDialog( "unchecked unfocused checkbox, [Variant 1], Variant 2, Variant 3, Cancel, *Ok*",
"Message 11",
new String [] {"Ok", "Cancel", "Variant 3", "Variant 2", "Variant 1"},
0, 1, Messages.getQuestionIcon(), new ProjectNewWindowDoNotAskOption());
// Case 12
Messages.showDialog( "unchecked unfocused checkbox, [Cancel], Variant 1, Variant 2, Variant 3, *Ok*",
"Message 12",
new String [] {"Ok", "Variant 3", "Variant 2", "Variant 1", "Cancel"},
0, 1, Messages.getQuestionIcon(), new ProjectNewWindowDoNotAskOption());
// Case 13
Messages.showDialog( "unchecked unfocused checkbox, [Cancel], Variant 1, Ok, Variant 2, Variant 3, *Ok*",
"Message 13",
new String [] {"Variant 3", "Variant 2", "Ok", "Variant 1", "Cancel"},
0, 1, Messages.getQuestionIcon(), new ProjectNewWindowDoNotAskOption());
}
});
}
}.start();
}
}
@@ -1,63 +0,0 @@
/*
* Copyright 2000-2015 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.notification.impl.actions;
import com.intellij.CommonBundle;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.impl.ProjectNewWindowDoNotAskOption;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.ui.Messages;
import javax.swing.*;
/**
* @author Denis Fokin
*/
public class CheckMessagesButtonsOrderAction extends AnAction implements DumbAware {
@Override
public void actionPerformed(AnActionEvent e) {
new Thread() {
@Override
public void run() {
super.run();
//noinspection SSBasedInspection
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
String message = "Proceed - focused, [space] ,Cancel - Nothing, Show ussages - default";
String[] options = {"Show usages", "Cancel", "Proceed"};
Messages.showDialog(message, "First Message", options, 0, 1, Messages.getQuestionIcon(), null);
Messages.showYesNoCancelDialog("unchecked unfocused checkbox, Yes - focused, space, Cancel, No Text - default",
IdeBundle.message("title.open.project"),
"This window",
"New Window",
CommonBundle.getCancelButtonText(),
Messages.getQuestionIcon(),
new ProjectNewWindowDoNotAskOption());
}
});
}
}.start();
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -70,8 +70,8 @@ public class ServiceManagerImpl implements BaseComponent {
@Override
public void extensionAdded(@NotNull final ServiceDescriptor descriptor, final PluginDescriptor pluginDescriptor) {
if (descriptor.overrides) {
ComponentAdapter oldAdapter =
picoContainer.unregisterComponent(descriptor.getInterface());// Allow to re-define service implementations in plugins.
// Allow to re-define service implementations in plugins.
ComponentAdapter oldAdapter = picoContainer.unregisterComponent(descriptor.getInterface());
if (oldAdapter == null) {
throw new RuntimeException("Service: " + descriptor.getInterface() + " doesn't override anything");
}
@@ -185,7 +185,6 @@ public abstract class ComponentStoreImpl implements IComponentStore.Reloadable {
errors = executeSave(session, readonlyFiles, errors);
}
}
return errors;
}
@@ -18,6 +18,7 @@ package com.intellij.openapi.components.impl.stores;
import com.intellij.CommonBundle;
import com.intellij.ide.highlighter.ProjectFileType;
import com.intellij.ide.highlighter.WorkspaceFileType;
import com.intellij.notification.Notifications;
import com.intellij.notification.NotificationsManager;
import com.intellij.openapi.application.*;
import com.intellij.openapi.components.*;
@@ -30,6 +31,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectBundle;
import com.intellij.openapi.project.impl.ProjectImpl;
import com.intellij.openapi.project.impl.ProjectManagerImpl;
import com.intellij.openapi.project.impl.ProjectManagerImpl.UnableToSaveProjectNotification;
import com.intellij.openapi.ui.MessageDialogBuilder;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Pair;
@@ -446,51 +448,69 @@ class ProjectStoreImpl extends BaseFileConfigurableStoreImpl implements IProject
@Override
protected final List<Throwable> doSave(@Nullable List<SaveSession> saveSessions, @NotNull List<Pair<SaveSession, VirtualFile>> readonlyFiles, @Nullable List<Throwable> errors) {
ProjectImpl.UnableToSaveProjectNotification[] notifications =
NotificationsManager.getNotificationsManager().getNotificationsOfType(ProjectImpl.UnableToSaveProjectNotification.class, myProject);
if (notifications.length > 0) {
throw new SaveCancelledException();
}
beforeSave(readonlyFiles);
super.doSave(saveSessions, readonlyFiles, errors);
if (!readonlyFiles.isEmpty()) {
ReadonlyStatusHandler.OperationStatus status;
AccessToken token = ReadAction.start();
try {
status = ReadonlyStatusHandler.getInstance(myProject).ensureFilesWritable(getFilesList(readonlyFiles));
UnableToSaveProjectNotification[] notifications =
NotificationsManager.getNotificationsManager().getNotificationsOfType(UnableToSaveProjectNotification.class, myProject);
if (readonlyFiles.isEmpty()) {
if (notifications.length > 0) {
for (UnableToSaveProjectNotification notification : notifications) {
notification.expire();
}
}
finally {
token.finish();
return errors;
}
if (notifications.length > 0) {
throw new SaveCancelledException();
}
ReadonlyStatusHandler.OperationStatus status;
AccessToken token = ReadAction.start();
try {
status = ReadonlyStatusHandler.getInstance(myProject).ensureFilesWritable(getFilesList(readonlyFiles));
}
finally {
token.finish();
}
if (status.hasReadonlyFiles()) {
dropUnableToSaveProjectNotification(myProject, status.getReadonlyFiles());
throw new SaveCancelledException();
}
else {
List<Pair<SaveSession, VirtualFile>> oldList = new ArrayList<Pair<SaveSession, VirtualFile>>(readonlyFiles);
readonlyFiles.clear();
for (Pair<SaveSession, VirtualFile> entry : oldList) {
errors = executeSave(entry.first, readonlyFiles, errors);
}
if (status.hasReadonlyFiles()) {
ProjectImpl.dropUnableToSaveProjectNotification(myProject, status.getReadonlyFiles());
if (errors != null) {
CompoundRuntimeException.doThrow(errors);
}
if (!readonlyFiles.isEmpty()) {
dropUnableToSaveProjectNotification(myProject, getFilesList(readonlyFiles));
throw new SaveCancelledException();
}
else {
List<Pair<SaveSession, VirtualFile>> oldList = new ArrayList<Pair<SaveSession, VirtualFile>>(readonlyFiles);
readonlyFiles.clear();
for (Pair<SaveSession, VirtualFile> entry : oldList) {
errors = executeSave(entry.first, readonlyFiles, errors);
}
if (errors != null) {
CompoundRuntimeException.doThrow(errors);
}
if (!readonlyFiles.isEmpty()) {
ProjectImpl.dropUnableToSaveProjectNotification(myProject, getFilesList(readonlyFiles));
throw new SaveCancelledException();
}
}
}
return errors;
}
private static void dropUnableToSaveProjectNotification(@NotNull Project project, @NotNull VirtualFile[] readOnlyFiles) {
UnableToSaveProjectNotification[] notifications =
NotificationsManager.getNotificationsManager().getNotificationsOfType(UnableToSaveProjectNotification.class, project);
if (notifications.length == 0) {
Notifications.Bus.notify(new UnableToSaveProjectNotification(project, readOnlyFiles), project);
}
else {
notifications[0].myFiles = readOnlyFiles;
}
}
protected void beforeSave(@NotNull List<Pair<SaveSession, VirtualFile>> readonlyFiles) {
}
@@ -3088,8 +3088,6 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
if (!Comparing.equal(color[i], currentColor)) {
currentColor = color[i] != null ? color[i] : JBColor.black;
UIUtil.updateLCDContrastBasingOnForegroundColor(g, currentColor);
g.setColor(currentColor);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -19,7 +19,7 @@ import com.intellij.ide.RecentProjectsManager;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.ide.startup.StartupManagerEx;
import com.intellij.notification.*;
import com.intellij.notification.NotificationsManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathMacros;
import com.intellij.openapi.application.ex.ApplicationEx;
@@ -54,9 +54,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.wm.WindowManager;
import com.intellij.openapi.wm.impl.FrameTitleBuilder;
import com.intellij.util.Function;
import com.intellij.util.TimedReference;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.pico.ConstructorInjectionComponentAdapter;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
@@ -65,7 +63,6 @@ import org.jetbrains.annotations.Nullable;
import org.picocontainer.*;
import javax.swing.*;
import javax.swing.event.HyperlinkEvent;
import java.io.File;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -520,59 +517,4 @@ public class ProjectImpl extends PlatformComponentManagerImpl implements Project
protected boolean logSlowComponents() {
return super.logSlowComponents() || ApplicationInfoImpl.getShadowInstance().isEAP();
}
public static void dropUnableToSaveProjectNotification(@NotNull final Project project, final VirtualFile[] readOnlyFiles) {
final UnableToSaveProjectNotification[] notifications =
NotificationsManager.getNotificationsManager().getNotificationsOfType(UnableToSaveProjectNotification.class, project);
if (notifications.length == 0) {
Notifications.Bus.notify(new UnableToSaveProjectNotification(project, readOnlyFiles), project);
}
}
public static class UnableToSaveProjectNotification extends Notification {
private Project myProject;
private final String[] myFileNames;
private UnableToSaveProjectNotification(@NotNull final Project project, final VirtualFile[] readOnlyFiles) {
super("Project Settings", "Could not save project!", buildMessage(), NotificationType.ERROR, new NotificationListener() {
@Override
public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
final UnableToSaveProjectNotification unableToSaveProjectNotification = (UnableToSaveProjectNotification)notification;
final Project _project = unableToSaveProjectNotification.getProject();
notification.expire();
if (_project != null && !_project.isDisposed()) {
_project.save();
}
}
});
myProject = project;
myFileNames = ContainerUtil.map(readOnlyFiles, new Function<VirtualFile, String>() {
@Override
public String fun(VirtualFile file) {
return file.getPresentableUrl();
}
}, new String[readOnlyFiles.length]);
}
public String[] getFileNames() {
return myFileNames;
}
private static String buildMessage() {
return "<p>Unable to save project files. Please ensure project files are writable and you have permissions to modify them." +
" <a href=\"\">Try to save project again</a>.</p>";
}
public Project getProject() {
return myProject;
}
@Override
public void expire() {
myProject = null;
super.expire();
}
}
}
@@ -23,6 +23,9 @@ import com.intellij.ide.RecentProjectsManager;
import com.intellij.ide.impl.ProjectUtil;
import com.intellij.ide.plugins.PluginManager;
import com.intellij.ide.startup.impl.StartupManagerImpl;
import com.intellij.notification.Notification;
import com.intellij.notification.NotificationListener;
import com.intellij.notification.NotificationType;
import com.intellij.notification.NotificationsManager;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.*;
@@ -42,7 +45,6 @@ import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.*;
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.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileEvent;
@@ -67,6 +69,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import javax.swing.event.HyperlinkEvent;
import java.io.File;
import java.io.IOException;
import java.util.*;
@@ -976,17 +979,30 @@ public class ProjectManagerImpl extends ProjectManagerEx implements PersistentSt
return true;
}
private static boolean ensureCouldCloseIfUnableToSave(@NotNull final Project project) {
final ProjectImpl.UnableToSaveProjectNotification[] notifications =
NotificationsManager.getNotificationsManager().getNotificationsOfType(ProjectImpl.UnableToSaveProjectNotification.class, project);
if (notifications.length == 0) return true;
private static boolean ensureCouldCloseIfUnableToSave(@NotNull Project project) {
UnableToSaveProjectNotification[] notifications =
NotificationsManager.getNotificationsManager().getNotificationsOfType(UnableToSaveProjectNotification.class, project);
if (notifications.length == 0) {
return true;
}
final String fileNames = StringUtil.join(notifications[0].getFileNames(), "\n");
StringBuilder message = new StringBuilder();
message.append(String.format("%s was unable to save some project files,\nare you sure you want to close this project anyway?",
ApplicationNamesInfo.getInstance().getProductName()));
final String msg = String.format("%s was unable to save some project files,\nare you sure you want to close this project anyway?",
ApplicationNamesInfo.getInstance().getProductName());
return Messages.showDialog(project, msg, "Unsaved Project", "Read-only files:\n\n" + fileNames, new String[]{"Yes", "No"}, 0, 1,
Messages.getWarningIcon()) == 0;
message.append("\n\nRead-only files:\n");
int count = 0;
VirtualFile[] files = notifications[0].myFiles;
for (VirtualFile file : files) {
if (count == 10) {
message.append('\n').append("and ").append(files.length - count).append(" more").append('\n');
}
else {
message.append(file.getPath()).append('\n');
count++;
}
}
return Messages.showYesNoDialog(project, message.toString(), "Unsaved Project", Messages.getWarningIcon()) == Messages.YES;
}
@@ -1039,4 +1055,34 @@ public class ProjectManagerImpl extends ProjectManagerEx implements PersistentSt
public String getPresentableName() {
return ProjectBundle.message("project.default.settings");
}
public static class UnableToSaveProjectNotification extends Notification {
private Project myProject;
public VirtualFile[] myFiles;
public UnableToSaveProjectNotification(@NotNull final Project project, final VirtualFile[] readOnlyFiles) {
super("Project Settings", "Could not save project", "Unable to save project files. Please ensure project files are writable and you have permissions to modify them." +
" <a href=\"\">Try to save project again</a>.", NotificationType.ERROR, new NotificationListener() {
@Override
public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
final UnableToSaveProjectNotification unableToSaveProjectNotification = (UnableToSaveProjectNotification)notification;
final Project _project = unableToSaveProjectNotification.myProject;
notification.expire();
if (_project != null && !_project.isDisposed()) {
_project.save();
}
}
});
myProject = project;
myFiles = readOnlyFiles;
}
@Override
public void expire() {
myProject = null;
super.expire();
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -98,17 +98,6 @@ public class DummyFileSystem extends DeprecatedVirtualFileSystem implements NonP
fireFileDeleted(requestor, vFile, vFile.getName(), parent);
}
@Override
public void moveFile(Object requestor, @NotNull VirtualFile vFile, @NotNull VirtualFile newParent) throws IOException {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public VirtualFile copyFile(Object requestor, @NotNull VirtualFile vFile, @NotNull VirtualFile newParent, @NotNull final String copyName) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public void renameFile(Object requestor, @NotNull VirtualFile vFile, @NotNull String newName) throws IOException {
final String oldName = vFile.getName();
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -84,27 +84,6 @@ public abstract class HttpFileSystemBase extends HttpFileSystem {
return createChild(vDir, fileName, false);
}
@Override
public void deleteFile(Object requestor, @NotNull VirtualFile vFile) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public void moveFile(Object requestor, @NotNull VirtualFile vFile, @NotNull VirtualFile newParent) throws IOException {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public VirtualFile copyFile(Object requestor, @NotNull VirtualFile vFile, @NotNull VirtualFile newParent, @NotNull final String copyName) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public void renameFile(Object requestor, @NotNull VirtualFile vFile, @NotNull String newName) throws IOException {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public String extractPresentableUrl(@NotNull String path) {
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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,6 +15,7 @@
*/
package com.intellij.openapi.vfs.newvfs.impl;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
@@ -24,6 +25,7 @@ import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.roots.OrderEnumerator;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
@@ -170,6 +172,18 @@ public class VfsRootAccess {
ourAdditionalRoots.add(FileUtil.toSystemIndependentName(root));
}
}
@TestOnly
public static void allowRootAccessTemporarily(@NotNull Disposable disposable, @NotNull final String... roots) {
for (String root : roots) {
ourAdditionalRoots.add(FileUtil.toSystemIndependentName(root));
}
Disposer.register(disposable, new Disposable() {
@Override
public void dispose() {
disallowRootAccess(roots);
}
});
}
@TestOnly
public static void disallowRootAccess(@NotNull String... roots) {
@@ -111,6 +111,9 @@ public class SheetController {
myResult = null;
int defaultButtonIndex = -1;
int focusedButtonIndex = -1;
for (int i = 0; i < buttons.length; i++) {
String buttonTitle = buttonTitles[i];
@@ -119,13 +122,18 @@ public class SheetController {
handleMnemonics(i, buttonTitle);
if (buttonTitle.equals(defaultButtonTitle)) {
myDefaultButton = buttons[i];
defaultButtonIndex = i;
}
if (buttonTitle.equals(focusedButton)) {
myFocusedButton = buttons[i];
focusedButtonIndex = i;
}
}
myFocusedButton = (focusedButtonIndex == -1) ? buttons[buttons.length - 1] : buttons[focusedButtonIndex];
myDefaultButton = (defaultButtonIndex == -1 && focusedButtonIndex != defaultButtonIndex) ? buttons[0] : buttons[defaultButtonIndex];
myDefaultButton = buttons[0];
if (myFocusedButton == null) {
myFocusedButton = myDefaultButton;
}
@@ -161,7 +161,6 @@
<action id="NextTab">
<keyboard-shortcut first-keystroke="alt RIGHT"/>
<keyboard-shortcut first-keystroke="control X" second-keystroke="N"/>
<keyboard-shortcut first-keystroke="control X" second-keystroke="O"/>
</action>
<action id="NextEditorTab">
<keyboard-shortcut first-keystroke="alt shift RIGHT"/>
@@ -262,7 +261,7 @@
<keyboard-shortcut first-keystroke="control 5"/>
</action>
<action id="NextSplitter">
<keyboard-shortcut first-keystroke="control X" second-keystrole="O"/>
<keyboard-shortcut first-keystroke="control X" second-keystroke="O"/>
</action>
<action id="Replace">
<keyboard-shortcut first-keystroke="shift alt 5"/>
@@ -635,7 +635,7 @@
<action id="TestMessageBoxAction" internal="true" class="com.intellij.diagnostic.TestMessageBoxAction" text="Show Test Dialog"/>
<separator/>
<group id="Internal.focusAndModality" popup="true" text="Focus and modality testing">
<action id="CheckMessagesButtonsOrderAction" internal="true" class="com.intellij.notification.impl.actions.CheckMessagesButtonsOrderAction"
<action id="CheckMessagesButtonsOrderAction" internal="true" class="com.intellij.internal.validation.CheckMessagesButtonsOrderAction"
text="Check Messages Buttons Order"/>
<action id="ShowDelayedMessageInternalAction" internal="true" class="com.intellij.notification.impl.actions.ShowDelayedMessageInternalAction"
text="Show Delayed Message"/>
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -25,7 +25,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
@@ -61,39 +60,6 @@ public class MockVirtualFileSystem extends DeprecatedVirtualFileSystem {
public void refresh(boolean asynchronous) {
}
@Override
public void deleteFile(Object requestor, @NotNull VirtualFile vFile) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public void moveFile(Object requestor, @NotNull VirtualFile vFile, @NotNull VirtualFile newParent) throws IOException {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public VirtualFile copyFile(Object requestor, @NotNull VirtualFile vFile, @NotNull VirtualFile newParent, @NotNull final String copyName) throws IOException {
throw new UnsupportedOperationException();
}
@Override
public void renameFile(Object requestor, @NotNull VirtualFile vFile, @NotNull String newName) throws IOException {
throw new UnsupportedOperationException();
}
@NotNull
@Override
public VirtualFile createChildFile(Object requestor, @NotNull VirtualFile vDir, @NotNull String fileName) throws IOException {
throw new UnsupportedOperationException();
}
@Override
@NotNull
public VirtualFile createChildDirectory(Object requestor, @NotNull VirtualFile vDir, @NotNull String dirName) throws IOException {
throw new IOException();
}
@Override
public VirtualFile refreshAndFindFileByPath(@NotNull String path) {
return findFileByPath(path);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -24,7 +24,6 @@ import static com.intellij.util.BitUtil.isSet;
* @version 11.1
* @see FileSystemUtil#getAttributes(String)
*/
@SuppressWarnings("OctalInteger")
public final class FileAttributes {
public enum Type { FILE, DIRECTORY, SPECIAL }
@@ -71,8 +71,6 @@ public class GraphicsUtil {
g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
enableAA ? RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HBGR : RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
}
UIUtil.setHintingForLCDText(g);
}
}
@@ -1771,56 +1771,6 @@ public class UIUtil {
Map map = (Map)tk.getDesktopProperty("awt.font.desktophints");
if (map != null) {
g2d.addRenderingHints(map);
setHintingForLCDText(g2d);
}
}
private static int THEME_BASED_TEXT_LCD_CONTRAST = 0;
private static int BEST_DARK_LCD_CONTRAST = 250;
private static int BEST_LIGHT_LCD_CONTRAST = 100;
public static int getContrastForColor (Color color) {
// YIQ
int yiqValue = ((color.getRed() * 299) + (color.getGreen() * 587) + (color.getBlue() * 114)) / 1000;
return yiqValue * 150/255 + 100;
}
public static void updateLCDContrastBasingOnForegroundColor(Graphics g, Color color) {
Graphics2D g2d = (Graphics2D)g;
if (SystemInfo.isJetbrainsJvm && Registry.is("force.subpixel.hinting")) {
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_LCD_CONTRAST, getContrastForColor(color));
}
}
public static void setHintingForLCDText(Graphics2D g2d) {
if (SystemInfo.isJetbrainsJvm && Registry.is("force.subpixel.hinting")) {
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
// According to JavaDoc we can set values form 100 to 250
// So we can use 0 as a special flag
int registryLcdContrastValue = Registry.intValue("lcd.contrast.value");
if (registryLcdContrastValue == THEME_BASED_TEXT_LCD_CONTRAST) {
if (isUnderDarcula()) {
registryLcdContrastValue = BEST_DARK_LCD_CONTRAST;
} else {
registryLcdContrastValue = BEST_LIGHT_LCD_CONTRAST;
}
}
// Wrong values prevent IDE from start
// So we have to be careful
if (registryLcdContrastValue < 100) {
LOG.warn("Wrong value of text LCD contrast " + registryLcdContrastValue);
registryLcdContrastValue = 100;
} else if (registryLcdContrastValue > 250) {
LOG.warn("Wrong value of text LCD contrast " + registryLcdContrastValue);
registryLcdContrastValue = 250;
}
g2d.setRenderingHint(RenderingHints.KEY_TEXT_LCD_CONTRAST, registryLcdContrastValue);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -21,11 +21,8 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
public class VcsFileSystem extends DeprecatedVirtualFileSystem {
public static final String COULD_NOT_IMPLEMENT_MESSAGE = VcsBundle.message("exception.text.internal.errror.could.not.implement.method");
private static final String PROTOCOL = "vcs";
@@ -72,37 +69,4 @@ public class VcsFileSystem extends DeprecatedVirtualFileSystem {
protected void fireBeforeContentsChange(Object requestor, @NotNull VirtualFile file) {
super.fireBeforeContentsChange(requestor, file);
}
@Override
public void deleteFile(Object requestor, @NotNull VirtualFile vFile) throws IOException {
throw new RuntimeException(COULD_NOT_IMPLEMENT_MESSAGE);
}
@Override
public void moveFile(Object requestor, @NotNull VirtualFile vFile, @NotNull VirtualFile newParent) throws IOException {
throw new RuntimeException(COULD_NOT_IMPLEMENT_MESSAGE);
}
@NotNull
@Override
public VirtualFile copyFile(Object requestor, @NotNull VirtualFile vFile, @NotNull VirtualFile newParent, @NotNull final String copyName) throws IOException {
throw new RuntimeException(COULD_NOT_IMPLEMENT_MESSAGE);
}
@Override
public void renameFile(Object requestor, @NotNull VirtualFile vFile, @NotNull String newName) throws IOException {
throw new RuntimeException(COULD_NOT_IMPLEMENT_MESSAGE);
}
@NotNull
@Override
public VirtualFile createChildFile(Object requestor, @NotNull VirtualFile vDir, @NotNull String fileName) throws IOException {
throw new RuntimeException(COULD_NOT_IMPLEMENT_MESSAGE);
}
@Override
@NotNull
public VirtualFile createChildDirectory(Object requestor, @NotNull VirtualFile vDir, @NotNull String dirName) throws IOException {
throw new RuntimeException(COULD_NOT_IMPLEMENT_MESSAGE);
}
}
@@ -1283,6 +1283,10 @@
key="bigdecimal.legacy.method.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.language.level.specific.issues.and.migration.aids" enabledByDefault="false" level="WARNING"
implementationClass="com.siyeh.ig.migration.BigDecimalLegacyMethodInspection"/>
<localInspection groupPath="Java" language="JAVA" shortName="EqualsReplaceableByObjectsCall" bundle="com.siyeh.InspectionGadgetsBundle"
key="equals.replaceable.by.objects.call.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.language.level.specific.issues.and.migration.aids" enabledByDefault="false" level="WARNING"
implementationClass="com.siyeh.ig.migration.EqualsReplaceableByObjectsCallInspection"/>
<localInspection groupPath="Java" language="JAVA" shortName="EnumerationCanBeIteration" bundle="com.siyeh.InspectionGadgetsBundle"
key="enumeration.can.be.iteration.display.name" groupBundle="messages.InspectionsBundle"
groupKey="group.names.language.level.specific.issues.and.migration.aids" enabledByDefault="false" level="WARNING"
@@ -2151,4 +2151,7 @@ use.of.clone.reference.problem.descriptor=Use of <code>#ref</code>
dangling.javadoc.display.name=Dangling Javadoc comment
dangling.javadoc.problem.descriptor=Dangling Javadoc comment #loc
dangling.javadoc.convert.quickfix=Replace with block comment
dangling.javadoc.delete.quickfix=Remove dangling comment
dangling.javadoc.delete.quickfix=Remove dangling comment
equals.replaceable.by.objects.call.display.name='equals()' expression replaceable by 'Objects.equals()' expression
equals.replaceable.by.objects.call.problem.descriptor=<code>#ref</code> replaceable by 'Objects.equals()' expression #loc
equals.replaceable.by.objects.call.quickfix=Replace with 'Objects.equals()' expression
@@ -0,0 +1,209 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.siyeh.ig.migration;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.siyeh.HardcodedMethodConstants;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.PsiReplacementUtil;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import com.siyeh.ig.psiutils.VariableAccessUtils;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Bas Leijdekkers
*/
public class EqualsReplaceableByObjectsCallInspection extends BaseInspection {
@Nls
@NotNull
@Override
public String getDisplayName() {
return InspectionGadgetsBundle.message("equals.replaceable.by.objects.call.display.name");
}
@NotNull
@Override
protected String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message("equals.replaceable.by.objects.call.problem.descriptor");
}
@Nullable
@Override
protected InspectionGadgetsFix buildFix(Object... infos) {
return new EqualsReplaceableByObjectsCallFix((String)infos[0], (String)infos[1], (Boolean)infos[2]);
}
private static class EqualsReplaceableByObjectsCallFix extends InspectionGadgetsFix {
private final String myName1;
private final String myName2;
private final Boolean myEquals;
public EqualsReplaceableByObjectsCallFix(String name1, String name2, Boolean equals) {
myName1 = name1;
myName2 = name2;
myEquals = equals;
}
@Nls
@NotNull
@Override
public String getName() {
return InspectionGadgetsBundle.message("equals.replaceable.by.objects.call.quickfix");
}
@NotNull
@Override
public String getFamilyName() {
return getName();
}
@Override
protected void doFix(Project project, ProblemDescriptor descriptor) {
final PsiElement element = descriptor.getPsiElement();
if (!(element instanceof PsiBinaryExpression)) {
return;
}
final PsiBinaryExpression expression = (PsiBinaryExpression)element;
if (myEquals) {
PsiReplacementUtil.replaceExpressionAndShorten(expression, "java.util.Objects.equals(" + myName1 + "," + myName2 + ")");
}
else {
PsiReplacementUtil.replaceExpressionAndShorten(expression, "!java.util.Objects.equals(" + myName1 + "," + myName2 + ")");
}
}
}
@Override
public boolean shouldInspect(PsiFile file) {
return PsiUtil.isLanguageLevel7OrHigher(file);
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new EqualsReplaceableByObjectsCallVisitor();
}
private static class EqualsReplaceableByObjectsCallVisitor extends BaseInspectionVisitor {
@Override
public void visitBinaryExpression(PsiBinaryExpression expression) {
final IElementType tokenType = expression.getOperationTokenType();
if (JavaTokenType.ANDAND.equals(tokenType)) {
final PsiVariable variable = ExpressionUtils.getVariableFromNullComparison(expression.getLOperand(), false);
if (variable == null) {
return;
}
final PsiVariable otherVariable = getArgumentFromEqualsCallOn(expression.getROperand(), variable);
if (otherVariable == null) {
return;
}
checkEqualityBefore(expression, true, variable, otherVariable);
}
else if (JavaTokenType.OROR.equals(tokenType)) {
final PsiVariable variable = ExpressionUtils.getVariableFromNullComparison(expression.getLOperand(), true);
if (variable == null) {
return;
}
final PsiExpression rhs = ParenthesesUtils.stripParentheses(expression.getROperand());
if (!(rhs instanceof PsiPrefixExpression)) {
return;
}
final PsiPrefixExpression prefixExpression = (PsiPrefixExpression)rhs;
if (!JavaTokenType.EXCL.equals(prefixExpression.getOperationTokenType())) {
return;
}
final PsiVariable otherVariable = getArgumentFromEqualsCallOn(prefixExpression.getOperand(), variable);
if (otherVariable == null) {
return;
}
checkEqualityBefore(expression, false, variable, otherVariable);
}
}
private void checkEqualityBefore(PsiExpression expression, boolean equals, PsiVariable variable1, PsiVariable variable2) {
final PsiElement parent = PsiTreeUtil.skipParentsOfType(expression, PsiParenthesizedExpression.class);
if (parent instanceof PsiBinaryExpression) {
final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)parent;
if (PsiTreeUtil.isAncestor(binaryExpression.getROperand(), expression, false)) {
final PsiExpression lhs = binaryExpression.getLOperand();
if (isEquality(lhs, equals, variable1, variable2)) {
registerError(binaryExpression, variable1.getName(), variable2.getName(), Boolean.valueOf(equals));
return;
}
}
}
registerError(expression, variable1.getName(), variable2.getName(), Boolean.valueOf(equals));
}
private static boolean isEquality(PsiExpression expression, boolean equals, PsiVariable variable1, PsiVariable variable2) {
expression = ParenthesesUtils.stripParentheses(expression);
if (!(expression instanceof PsiBinaryExpression)) {
return false;
}
final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)expression;
if (equals) {
if (!JavaTokenType.EQEQ.equals(binaryExpression.getOperationTokenType())) {
return false;
}
}
else {
if (!JavaTokenType.NE.equals(binaryExpression.getOperationTokenType())) {
return false;
}
}
final PsiExpression lhs = binaryExpression.getLOperand();
final PsiExpression rhs = binaryExpression.getROperand();
return (VariableAccessUtils.evaluatesToVariable(lhs, variable1) && VariableAccessUtils.evaluatesToVariable(rhs, variable2)) ||
(VariableAccessUtils.evaluatesToVariable(lhs, variable2) && VariableAccessUtils.evaluatesToVariable(rhs, variable1));
}
private static PsiVariable getArgumentFromEqualsCallOn(PsiExpression expression, @NotNull PsiVariable variable) {
expression = ParenthesesUtils.stripParentheses(expression);
if (!(expression instanceof PsiMethodCallExpression)) {
return null;
}
final PsiMethodCallExpression methodCallExpression = (PsiMethodCallExpression)expression;
final PsiReferenceExpression methodExpression = methodCallExpression.getMethodExpression();
final String methodName = methodExpression.getReferenceName();
if (!HardcodedMethodConstants.EQUALS.equals(methodName)) {
return null;
}
final PsiExpression qualifier = methodExpression.getQualifierExpression();
if (!VariableAccessUtils.evaluatesToVariable(qualifier, variable)) {
return null;
}
final PsiExpressionList argumentList = methodCallExpression.getArgumentList();
final PsiExpression[] expressions = argumentList.getExpressions();
if (expressions.length != 1) {
return null;
}
return ExpressionUtils.getVariable(expressions[0]);
}
}
}
@@ -593,4 +593,48 @@ public class ExpressionUtils {
final IElementType tokenType = prefixExpression.getOperationTokenType();
return JavaTokenType.MINUS.equals(tokenType);
}
@Nullable
public static PsiVariable getVariableFromNullComparison(PsiExpression expression, boolean equals) {
expression = ParenthesesUtils.stripParentheses(expression);
if (!(expression instanceof PsiPolyadicExpression)) {
return null;
}
final PsiPolyadicExpression polyadicExpression = (PsiPolyadicExpression)expression;
final IElementType tokenType = polyadicExpression.getOperationTokenType();
if (equals) {
if (!JavaTokenType.EQEQ.equals(tokenType)) {
return null;
}
}
else {
if (!JavaTokenType.NE.equals(tokenType)) {
return null;
}
}
final PsiExpression[] operands = polyadicExpression.getOperands();
if (operands.length != 2) {
return null;
}
if (PsiType.NULL.equals(operands[0].getType())) {
return getVariable(operands[1]);
}
else if (PsiType.NULL.equals(operands[1].getType())) {
return getVariable(operands[0]);
}
return null;
}
public static PsiVariable getVariable(PsiExpression expression) {
expression = ParenthesesUtils.stripParentheses(expression);
if (!(expression instanceof PsiReferenceExpression)) {
return null;
}
final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)expression;
final PsiElement target = referenceExpression.resolve();
if (!(target instanceof PsiVariable)) {
return null;
}
return (PsiVariable)target;
}
}
@@ -0,0 +1,12 @@
<html>
<body>
Reports expressions that can be replaced with a call to <code>java.util.Objects.equals()</code>, which is available since JDK 1.7.
For example:
<code><pre>a != <b>null</b> <b>&&</b> a.equals(b)</pre></code>
<!-- tooltip end -->
<p>
This inspection only reports if the project or module is configured to use a language level of 7 or higher.
<p>
<small>New in 15</small>
</body>
</html>
@@ -0,0 +1,7 @@
class EqualsReplaceableByObjectsCall {
void yyy(Object a, Object b) {
boolean c = <warning descr="'(a != null) && a.equals(b)' replaceable by 'Objects.equals()' expression">(a != null) && a.equals(b)</warning>;
boolean d = <warning descr="'(a != b) && (a == null || !a.equals(b))' replaceable by 'Objects.equals()' expression">(a != b) && (a == null || !a.equals(b))</warning>;
boolean e = <warning descr="'((a) == (b)) || ((a) != (null) && (a).equals((b)))' replaceable by 'Objects.equals()' expression">((a) == (b)) || ((a) != (null) && (a).equals((b)))</warning>;
}
}
@@ -0,0 +1,37 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.siyeh.ig.migration;
import com.intellij.codeInspection.InspectionProfileEntry;
import com.siyeh.ig.LightInspectionTestCase;
import junit.framework.TestCase;
import org.jetbrains.annotations.Nullable;
/**
* @author Bas Leijdekkers
*/
public class EqualsReplaceableByObjectsCallInspectionTest extends LightInspectionTestCase {
public void testEqualsReplaceableByObjectsCall() {
doTest();
}
@Nullable
@Override
protected InspectionProfileEntry getInspection() {
return new EqualsReplaceableByObjectsCallInspection();
}
}
@@ -52,7 +52,7 @@ public class PsiDiffContentFactory {
if (containingFile == null) {
String text = psiElement.getText();
if (text == null) return null;
return DiffContentFactory.getInstance().create(text, psiElement.getLanguage().getAssociatedFileType());
return DiffContentFactory.getInstance().create(text, psiElement.getLanguage().getAssociatedFileType(), false);
}
DocumentContent wholeFileContent = DiffContentFactory.getInstance().createDocument(psiElement.getProject(), containingFile.getVirtualFile());
if (wholeFileContent == null) return null;
@@ -17,27 +17,20 @@ package org.jetbrains.plugins.gradle;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.SimpleJavaParameters;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.externalSystem.ExternalSystemAutoImportAware;
import com.intellij.openapi.externalSystem.ExternalSystemConfigurableAware;
import com.intellij.openapi.externalSystem.ExternalSystemManager;
import com.intellij.openapi.externalSystem.ExternalSystemUiAware;
import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
import com.intellij.openapi.externalSystem.model.execution.ExternalSystemTaskExecutionSettings;
import com.intellij.openapi.externalSystem.model.execution.ExternalTaskExecutionInfo;
import com.intellij.openapi.externalSystem.model.execution.ExternalTaskPojo;
import com.intellij.openapi.externalSystem.model.project.ExternalProjectPojo;
import com.intellij.openapi.externalSystem.model.project.ProjectData;
import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode;
import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback;
import com.intellij.openapi.externalSystem.service.project.ExternalSystemProjectResolver;
import com.intellij.openapi.externalSystem.service.project.autoimport.CachingExternalSystemAutoImportAware;
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManager;
import com.intellij.openapi.externalSystem.service.ui.DefaultExternalSystemUiAware;
import com.intellij.openapi.externalSystem.task.ExternalSystemTaskManager;
import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
@@ -45,7 +38,6 @@ import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ex.ProjectRootManagerEx;
import com.intellij.openapi.startup.StartupActivity;
import com.intellij.openapi.util.AtomicNotNullLazyValue;
import com.intellij.openapi.util.NotNullLazyValue;
@@ -291,38 +283,6 @@ public class GradleManager
ensureProjectsRefresh();
}
@Override
public void onProjectsLinked(@NotNull Collection<GradleProjectSettings> settings) {
final ProjectDataManager projectDataManager = ServiceManager.getService(ProjectDataManager.class);
for (GradleProjectSettings gradleProjectSettings : settings) {
ExternalSystemUtil.refreshProject(
project, GradleConstants.SYSTEM_ID, gradleProjectSettings.getExternalProjectPath(),
new ExternalProjectRefreshCallback() {
@Override
public void onSuccess(@Nullable final DataNode<ProjectData> externalProject) {
if (externalProject == null) {
return;
}
ExternalSystemApiUtil.executeProjectChangeAction(true, new DisposeAwareProjectChange(project) {
@Override
public void execute() {
ProjectRootManagerEx.getInstanceEx(project).mergeRootsChangesDuring(new Runnable() {
@Override
public void run() {
projectDataManager.importData(externalProject.getKey(), Collections.singleton(externalProject), project, true);
}
});
}
});
}
@Override
public void onFailure(@NotNull String errorMessage, @Nullable String errorDetails) {
}
}, false, ProgressExecutionMode.MODAL_SYNC);
}
}
private void ensureProjectsRefresh() {
ExternalSystemUtil.refreshProjects(project, GradleConstants.SYSTEM_ID, true);
}
@@ -80,7 +80,7 @@ public class GradleBuildProcessParametersProvider extends BuildProcessParameters
File[] children = FileUtil.notNullize(gradleLibDir.listFiles());
for (File child : children) {
final String fileName = child.getName();
if (fileName.endsWith(".jar") && !fileName.startsWith("logback-") && child.isFile()) {
if (fileName.endsWith(".jar") && child.isFile()) {
classpath.add(child.getAbsolutePath());
}
}
@@ -0,0 +1,36 @@
/*
* Copyright 2000-2015 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.plugins.gradle.service.execution;
import com.intellij.openapi.externalSystem.service.execution.NotSupportedException;
import org.gradle.tooling.CancellationToken;
import org.gradle.tooling.CancellationTokenSource;
/**
* @author Vladislav.Soroka
* @since 3/25/2015
*/
public class UnsupportedCancellationToken implements CancellationTokenSource {
@Override
public void cancel() {
throw new NotSupportedException("Configured version of Gradle does not support cancellation. \nPlease, use Gradle 2.1 or newer.");
}
@Override
public CancellationToken token() {
return null;
}
}
@@ -370,8 +370,11 @@ public class BaseGradleProjectResolverExtension implements GradleProjectResolver
@NotNull
@Override
public Set<Class> getExtraProjectModelClasses() {
return ContainerUtil.<Class>set(
GradleBuild.class, ExternalProject.class, ModuleExtendedModel.class, BuildScriptClasspathModel.class);
Set<Class> result = ContainerUtil.<Class>set(GradleBuild.class, ExternalProject.class, ModuleExtendedModel.class);
if (!resolverCtx.isPreviewMode()) {
result.add(BuildScriptClasspathModel.class);
}
return result;
}
@NotNull
@@ -35,6 +35,7 @@ import org.gradle.tooling.internal.consumer.DefaultExecutorServiceFactory;
import org.gradle.tooling.internal.consumer.DefaultGradleConnector;
import org.gradle.tooling.internal.consumer.Distribution;
import org.gradle.tooling.model.build.BuildEnvironment;
import org.gradle.util.GradleVersion;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.settings.DistributionType;
@@ -443,7 +444,18 @@ public class GradleExecutionHelper {
}
@Nullable
private static BuildEnvironment getBuildEnvironment(@NotNull ProjectConnection connection) {
public static GradleVersion getGradleVersion(@NotNull ProjectConnection connection) {
final BuildEnvironment buildEnvironment = getBuildEnvironment(connection);
GradleVersion gradleVersion = null;
if (buildEnvironment != null) {
gradleVersion = GradleVersion.version(buildEnvironment.getGradle().getGradleVersion());
}
return gradleVersion;
}
@Nullable
public static BuildEnvironment getBuildEnvironment(@NotNull ProjectConnection connection) {
try {
return connection.getModel(BuildEnvironment.class);
}
@@ -44,10 +44,12 @@ import org.gradle.tooling.model.build.BuildEnvironment;
import org.gradle.tooling.model.idea.BasicIdeaProject;
import org.gradle.tooling.model.idea.IdeaModule;
import org.gradle.tooling.model.idea.IdeaProject;
import org.gradle.util.GradleVersion;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.model.ProjectImportAction;
import org.jetbrains.plugins.gradle.remote.impl.GradleLibraryNamesMixer;
import org.jetbrains.plugins.gradle.service.execution.UnsupportedCancellationToken;
import org.jetbrains.plugins.gradle.settings.ClassHolder;
import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings;
import org.jetbrains.plugins.gradle.util.GradleConstants;
@@ -150,6 +152,11 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
parametersList.addProperty(jvmArg.getKey(), jvmArg.getValue());
}
final BuildEnvironment buildEnvironment = GradleExecutionHelper.getBuildEnvironment(resolverCtx.getConnection());
GradleVersion gradleVersion = null;
if (buildEnvironment != null) {
gradleVersion = GradleVersion.version(buildEnvironment.getGradle().getGradleVersion());
}
BuildActionExecuter<ProjectImportAction.AllModels> buildActionExecutor = resolverCtx.getConnection().action(projectImportAction);
@@ -169,6 +176,9 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
buildActionExecutor.withCancellationToken(cancellationTokenSource.token());
synchronized (myCancellationMap) {
myCancellationMap.putValue(resolverCtx.getExternalSystemTaskId(), cancellationTokenSource);
if (gradleVersion != null && gradleVersion.compareTo(GradleVersion.version("2.1")) < 0) {
myCancellationMap.putValue(resolverCtx.getExternalSystemTaskId(), new UnsupportedCancellationToken());
}
}
allModels = buildActionExecutor.run();
if (allModels == null) {
@@ -196,7 +206,6 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
}
}
final BuildEnvironment buildEnvironment = getBuildEnvironment(resolverCtx);
allModels.setBuildEnvironment(buildEnvironment);
resolverCtx.setModels(allModels);
@@ -280,16 +289,6 @@ public class GradleProjectResolver implements ExternalSystemProjectResolver<Grad
return projectDataNode;
}
@Nullable
private static BuildEnvironment getBuildEnvironment(@NotNull ProjectResolverContext resolverCtx) {
try {
return resolverCtx.getConnection().getModel(BuildEnvironment.class);
}
catch (Exception e) {
return null;
}
}
private void handleBuildSrcProject(@NotNull final DataNode<ProjectData> resultProjectDataNode,
@NotNull final ProjectConnectionDataNodeFunction projectConnectionDataNodeFunction) {
@@ -32,11 +32,13 @@ import org.gradle.tooling.BuildLauncher;
import org.gradle.tooling.CancellationTokenSource;
import org.gradle.tooling.GradleConnector;
import org.gradle.tooling.ProjectConnection;
import org.gradle.util.GradleVersion;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.service.project.GradleExecutionHelper;
import org.jetbrains.plugins.gradle.service.project.GradleProjectResolver;
import org.jetbrains.plugins.gradle.service.project.GradleProjectResolverExtension;
import org.jetbrains.plugins.gradle.service.execution.UnsupportedCancellationToken;
import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings;
import org.jetbrains.plugins.gradle.util.GradleConstants;
@@ -118,11 +120,17 @@ public class GradleTaskManager extends AbstractExternalSystemTaskManager<GradleE
}
}
GradleVersion gradleVersion = GradleExecutionHelper.getGradleVersion(connection);
BuildLauncher launcher = myHelper.getBuildLauncher(id, connection, settings, listener, vmOptions, scriptParameters);
launcher.forTasks(ArrayUtil.toStringArray(taskNames));
final CancellationTokenSource cancellationTokenSource = GradleConnector.newCancellationTokenSource();
launcher.withCancellationToken(cancellationTokenSource.token());
myCancellationMap.put(id, cancellationTokenSource);
if (gradleVersion != null && gradleVersion.compareTo(GradleVersion.version("2.1")) < 0) {
myCancellationMap.put(id, new UnsupportedCancellationToken());
} else {
final CancellationTokenSource cancellationTokenSource = GradleConnector.newCancellationTokenSource();
launcher.withCancellationToken(cancellationTokenSource.token());
myCancellationMap.put(id, cancellationTokenSource);
}
try {
launcher.run();
}
@@ -1,23 +1,6 @@
package org.jetbrains.plugins.gradle.util;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.ThrowableProxy;
import ch.qos.logback.core.AppenderBase;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTask;
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskState;
import com.intellij.openapi.externalSystem.service.internal.ExternalSystemProcessingManager;
import com.intellij.openapi.externalSystem.service.notification.ExternalSystemNotificationManager;
import com.intellij.openapi.externalSystem.service.notification.NotificationCategory;
import com.intellij.openapi.externalSystem.service.notification.NotificationData;
import com.intellij.openapi.externalSystem.service.notification.NotificationSource;
import com.intellij.openapi.project.Project;
import org.gradle.tooling.internal.consumer.connection.NonCancellableConsumerConnectionAdapter;
import org.jetbrains.plugins.gradle.service.notification.OpenGradleSettingsCallback;
import java.util.List;
/**
* @author Denis Zhdanov
@@ -27,65 +10,6 @@ public class GradleLog {
public static final Logger LOG = Logger.getInstance(GradleLog.class);
private static final String GRADLE_PROVIDER_DOES_NOT_SUPPORT_CANCELLATION_MESSAGE =
"Note: Version of Gradle provider does not support cancellation. Upgrade your Gradle build.";
private GradleLog() {
}
public static class GradleLogbackAppender extends AppenderBase<ILoggingEvent> {
@Override
protected void append(ILoggingEvent event) {
ThrowableProxy throwableProxy =
event.getThrowableProxy() instanceof ThrowableProxy ? (ThrowableProxy)event.getThrowableProxy() : null;
Throwable throwable = throwableProxy == null ? null : throwableProxy.getThrowable();
switch (event.getLevel().toInt()) {
case Level.ALL_INT:
case Level.TRACE_INT:
case Level.DEBUG_INT:
LOG.debug(event.getFormattedMessage(), throwable);
break;
case Level.INFO_INT:
LOG.info(event.getFormattedMessage(), throwable);
break;
case Level.WARN_INT:
LOG.warn(event.getFormattedMessage(), throwable);
break;
case Level.ERROR_INT:
LOG.error(event.getFormattedMessage(), throwable);
break;
case Level.OFF_INT:
break;
default:
LOG.debug(event.getFormattedMessage(), throwable);
break;
}
if (NonCancellableConsumerConnectionAdapter.class.getName().equals(event.getLoggerName()) &&
GRADLE_PROVIDER_DOES_NOT_SUPPORT_CANCELLATION_MESSAGE.equals(event.getMessage())) {
// see org.gradle.tooling.internal.consumer.connection.NonCancellableConsumerConnectionAdapter#handleCancellationPreOperation
ExternalSystemProcessingManager processingManager = ServiceManager.getService(ExternalSystemProcessingManager.class);
final List<ExternalSystemTask> canceledTasks =
processingManager
.findTasksOfState(GradleConstants.SYSTEM_ID, ExternalSystemTaskState.CANCELING, ExternalSystemTaskState.CANCELED);
for (ExternalSystemTask canceledTask : canceledTasks) {
final Project project = canceledTask.getId().findProject();
if (project != null) {
String errorMessage = String.format("%s <a href=\"%s\">Open Gradle settings</a>",
"Configured version of Gradle does not support cancellation. Please, use Gradle 2.1 or newer.\n",
OpenGradleSettingsCallback.ID);
NotificationData notification = new NotificationData(
"Gradle supports cancellation since 2.1 version", errorMessage, NotificationCategory.WARNING,
NotificationSource.PROJECT_SYNC);
notification.setListener(OpenGradleSettingsCallback.ID, new OpenGradleSettingsCallback(project));
notification.setBalloonNotification(true);
ExternalSystemNotificationManager.getInstance(project).showNotification(GradleConstants.SYSTEM_ID, notification);
}
}
}
}
}
}
@@ -55,10 +55,6 @@ public class ProjectImportAction implements BuildAction<ProjectImportAction.AllM
}
AllModels allModels = new AllModels(ideaProject);
// TODO ask gradle guys why there is always null got for BuildEnvironment model
//allModels.setBuildEnvironment(controller.findModel(BuildEnvironment.class));
addExtraProject(controller, allModels, null);
for (IdeaModule module : ideaProject.getModules()) {
addExtraProject(controller, allModels, module);
@@ -207,7 +207,36 @@ class InProcessGroovyc implements GroovycFlavor {
return pair.second;
}
final ClassDependencyLoader checkWellFormed = new ClassDependencyLoader();
final ClassDependencyLoader checkWellFormed = new ClassDependencyLoader() {
@Override
protected void loadClassDependencies(Class aClass) throws ClassNotFoundException {
if (!isCompilerCoreClass(aClass.getName()) || !(aClass.getClassLoader() instanceof UrlClassLoader)) {
super.loadClassDependencies(aClass);
}
}
private boolean isCompilerCoreClass(String name) {
if (name.startsWith("groovyjarjar")) {
return true;
}
if (name.startsWith("org.codehaus.groovy.")) {
String tail = name.substring("org.codehaus.groovy.".length());
if (tail.startsWith("ast") ||
tail.startsWith("classgen") ||
tail.startsWith("tools.javac") ||
tail.startsWith("antlr") ||
tail.startsWith("vmplugin") ||
tail.startsWith("reflection") ||
tail.startsWith("control")) {
return true;
}
if (tail.startsWith("runtime") && name.contains("GroovyMethods")) {
return true;
}
}
return false;
}
};
UrlClassLoader groovyAllLoader = UrlClassLoader.build().
urls(toUrls(ContainerUtil.concat(GroovyBuilder.getGroovyRtRoots(), Collections.singletonList(groovyAll)))).allowLock().
useCache(ourLoaderCachePool, new UrlClassLoader.CachingCondition() {
@@ -23,73 +23,74 @@ import java.util.Set;
* @author peter
*/
public class ClassDependencyLoader {
private final Set<Class> myVisited = new HashSet<Class>();
/**
* @param aClass
* @return aClass
* @throws ClassNotFoundException when any of the classes can't be loaded, that's referenced in aClass' fields, methods etc. recursively
* @throws ClassNotFoundException when any of the classes can't be loaded, that's referenced in aClass' fields, methods etc. recursively
*/
public Class loadDependencies(Class aClass) throws ClassNotFoundException {
loadClassDependencies(aClass, new HashSet<Class>());
loadClassDependencies(aClass);
return aClass;
}
private void loadTypeDependencies(Type aClass, Set<Class> visited) throws ClassNotFoundException {
private void loadTypeDependencies(Type aClass) throws ClassNotFoundException {
if (aClass instanceof Class) {
loadClassDependencies((Class)aClass, visited);
loadClassDependencies((Class)aClass);
}
else if (aClass instanceof ParameterizedType) {
loadTypeDependencies(((ParameterizedType)aClass).getOwnerType(), visited);
loadTypeDependencies(((ParameterizedType)aClass).getOwnerType());
for (Type type : ((ParameterizedType)aClass).getActualTypeArguments()) {
loadTypeDependencies(type, visited);
loadTypeDependencies(type);
}
}
else if (aClass instanceof WildcardType) {
for (Type type : ((WildcardType)aClass).getLowerBounds()) {
loadTypeDependencies(type, visited);
loadTypeDependencies(type);
}
for (Type type : ((WildcardType)aClass).getUpperBounds()) {
loadTypeDependencies(type, visited);
loadTypeDependencies(type);
}
}
else if (aClass instanceof GenericArrayType) {
loadTypeDependencies(((GenericArrayType)aClass).getGenericComponentType(), visited);
loadTypeDependencies(((GenericArrayType)aClass).getGenericComponentType());
}
}
protected void loadClassDependencies(Class aClass, Set<Class> visited) throws ClassNotFoundException {
protected void loadClassDependencies(Class aClass) throws ClassNotFoundException {
String name = aClass.getName();
if (visited.add(aClass)) {
if (myVisited.add(aClass)) {
try {
for (Method method : aClass.getDeclaredMethods()) {
loadTypeDependencies(method.getGenericReturnType(), visited);
loadTypeDependencies(method.getGenericReturnType());
for (Type type : method.getGenericExceptionTypes()) {
loadTypeDependencies(type, visited);
loadTypeDependencies(type);
}
for (Type type : method.getGenericParameterTypes()) {
loadTypeDependencies(type, visited);
loadTypeDependencies(type);
}
}
for (Constructor method : aClass.getDeclaredConstructors()) {
for (Type type : method.getGenericExceptionTypes()) {
loadTypeDependencies(type, visited);
loadTypeDependencies(type);
}
for (Type type : method.getGenericParameterTypes()) {
loadTypeDependencies(type, visited);
loadTypeDependencies(type);
}
}
for (Field field : aClass.getDeclaredFields()) {
loadTypeDependencies(field.getGenericType(), visited);
loadTypeDependencies(field.getGenericType());
}
Type superclass = aClass.getGenericSuperclass();
if (superclass != null) {
loadClassDependencies(aClass, visited);
loadClassDependencies(aClass);
}
for (Type intf : aClass.getGenericInterfaces()) {
loadTypeDependencies(intf, visited);
loadTypeDependencies(intf);
}
aClass.getAnnotations();
@@ -468,9 +468,9 @@ public class DependentGroovycRunner {
static GroovyClassLoader buildClassLoaderFor(final CompilerConfiguration compilerConfiguration, final AstAwareResourceLoader resourceLoader) {
final ClassDependencyLoader checkWellFormed = new ClassDependencyLoader() {
@Override
protected void loadClassDependencies(Class aClass, Set<Class> visited) throws ClassNotFoundException {
protected void loadClassDependencies(Class aClass) throws ClassNotFoundException {
if (resourceLoader.getSourceFile(aClass.getName()) == null) return;
super.loadClassDependencies(aClass, visited);
super.loadClassDependencies(aClass);
}
};
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -44,16 +44,12 @@ public class BasicBlock implements IGraphNode {
private List<BasicBlock> succs = new ArrayList<BasicBlock>();
private List<Integer> instrOldOffsets = new ArrayList<Integer>();
private final List<Integer> instrOldOffsets = new ArrayList<Integer>();
private List<BasicBlock> predExceptions = new ArrayList<BasicBlock>();
private List<BasicBlock> succExceptions = new ArrayList<BasicBlock>();
public BasicBlock() {
}
public BasicBlock(int id) {
this.id = id;
}
@@ -63,11 +59,10 @@ public class BasicBlock implements IGraphNode {
// *****************************************************************************
public Object clone() {
BasicBlock block = new BasicBlock(id);
BasicBlock block = new BasicBlock();
block.id = id;
block.setSeq(seq.clone());
block.setInstrOldOffsets(new ArrayList<Integer>(instrOldOffsets));
block.instrOldOffsets.addAll(instrOldOffsets);
return block;
}
@@ -220,10 +215,6 @@ public class BasicBlock implements IGraphNode {
return instrOldOffsets;
}
public void setInstrOldOffsets(List<Integer> instrInds) {
this.instrOldOffsets = instrInds;
}
public List<? extends IGraphNode> getPredecessors() {
List<BasicBlock> lst = new ArrayList<BasicBlock>(preds);
lst.addAll(predExceptions);
@@ -296,7 +296,7 @@ public class ControlFlowGraph implements CodeConstants {
VBStyleCollection<BasicBlock, Integer> col = new VBStyleCollection<BasicBlock, Integer>();
InstructionSequence currseq = null;
ArrayList<Integer> lstOffs = null;
List<Integer> lstOffs = null;
int len = startblock.length;
short counter = 0;
@@ -306,14 +306,11 @@ public class ControlFlowGraph implements CodeConstants {
for (int i = 0; i < len; i++) {
if (startblock[i] == 1) {
currentBlock = new BasicBlock();
currentBlock.id = ++counter;
currentBlock = new BasicBlock(++counter);
currseq = new SimpleInstructionSequence();
lstOffs = new ArrayList<Integer>();
currseq = currentBlock.getSeq();
lstOffs = currentBlock.getInstrOldOffsets();
currentBlock.setSeq(currseq);
currentBlock.setInstrOldOffsets(lstOffs);
col.addWithKey(currentBlock, currentBlock.id);
blockoffset = instrseq.getOffset(i);
@@ -766,9 +763,7 @@ public class ControlFlowGraph implements CodeConstants {
first = blocks.get(0);
last = new BasicBlock();
last.id = ++last_id;
last.setSeq(new SimpleInstructionSequence());
last = new BasicBlock(++last_id);
for (BasicBlock block : blocks) {
if (block.getSuccs().isEmpty()) {
@@ -101,6 +101,8 @@ public class BytecodeMappingTracer {
}
Map<Integer, Integer> res = new HashMap<Integer, Integer>();
// first match offsets from line number table
int[] data = lineNumberTable.getRawData();
for (int i = 0; i < data.length; i += 2) {
int originalOffset = data[i];
@@ -113,9 +115,11 @@ public class BytecodeMappingTracer {
unmappedLines.add(originalLine);
}
}
// now match offsets from decompiler mapping
for (Entry<Integer, Integer> entry : mapping.entrySet()) {
int originalLine = lineNumberTable.findLineNumber(entry.getKey());
if (originalLine > -1) {
if (originalLine > -1 && !res.containsKey(originalLine)) {
res.put(originalLine, entry.getValue());
unmappedLines.remove(originalLine);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2014 JetBrains s.r.o.
* Copyright 2000-2015 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.
@@ -889,13 +889,16 @@ public class FinallyProcessor {
if (seqPattern.length() < seqSample.length()) { // split in two blocks
SimpleInstructionSequence seq = new SimpleInstructionSequence();
LinkedList<Integer> oldOffsets = new LinkedList<Integer>();
for (int i = seqSample.length() - 1; i >= seqPattern.length(); i--) {
seq.addInstruction(0, seqSample.getInstr(i), -1);
oldOffsets.addFirst(sample.getOldOffset(i));
seqSample.removeInstruction(i);
}
BasicBlock newblock = new BasicBlock(++graph.last_id);
newblock.setSeq(seq);
newblock.getInstrOldOffsets().addAll(oldOffsets);
List<BasicBlock> lstTemp = new ArrayList<BasicBlock>();
lstTemp.addAll(sample.getSuccs());
@@ -1038,7 +1041,7 @@ public class FinallyProcessor {
// new empty block
BasicBlock emptyblock = new BasicBlock(++graph.last_id);
emptyblock.setSeq(new SimpleInstructionSequence());
graph.getBlocks().addWithKey(emptyblock, emptyblock.id);
// add to ranges if necessary
@@ -12,9 +12,9 @@ class i implements bg {
private final b b;
i(b var1, j var2) {
this.b = var1;
this.b = var1;// 1
this.a = var2;
}// 1
}
public void a(c var1, k var2, boolean var3) {
File var4 = this.a.b().a(var1);// 2
@@ -50,7 +50,7 @@ class 'a/a/a/a/e/f/i' {
Lines mapping:
0 <-> 25
1 <-> 17
1 <-> 15
2 <-> 20
3 <-> 21
4 <-> 22
@@ -13,7 +13,7 @@ public class TestClassLoop {
while(true) {
try {
if(!var0) {// 33
return;
return;// 34
}
} finally {
System.out.println("1");// 38
@@ -37,7 +37,7 @@ public class TestClassLoop {
}
}
System.out.println("4");
System.out.println("4");// 58
}
}
}
@@ -54,6 +54,7 @@ class 'pkg/TestClassLoop' {
4 10
d 10
f 14
1a 15
26 18
27 18
2a 18
@@ -71,6 +72,9 @@ class 'pkg/TestClassLoop' {
2a 33
2d 33
2f 33
37 39
3a 39
3c 39
}
}
@@ -78,13 +82,13 @@ Lines mapping:
23 <-> 6
29 <-> 11
33 <-> 15
34 <-> 16
38 <-> 19
45 <-> 25
49 <-> 30
52 <-> 33
53 <-> 34
58 <-> 40
Not mapped:
34
39
54
58
@@ -50,6 +50,7 @@ class 'pkg/TestClassVar' {
20 11
26 12
29 12
2e 7
34 18
}
@@ -18,12 +18,12 @@ public enum TestEnum {
}// 30
private TestEnum() {
this("?");
}// 34
this("?");// 34
}
private TestEnum(@Deprecated String var3) {
this.s = var3;
}// 35
this.s = var3;// 35
}
}
class 'pkg/TestEnum$1' {
@@ -59,5 +59,5 @@ Lines mapping:
22 <-> 7
27 <-> 12
30 <-> 18
34 <-> 22
35 <-> 26
34 <-> 21
35 <-> 25
@@ -36,7 +36,7 @@ public class TestTryCatchFinally {
System.out.println("Finally");// 55
}
return -1;
return -1;// 56
}
}
@@ -67,13 +67,16 @@ class 'pkg/TestTryCatchFinally' {
method 'test (Ljava/lang/String;)I' {
1 30
4 30
e 31
10 33
1a 33
23 33
26 33
31 38
34 35
35 35
38 35
3f 38
}
}
@@ -90,11 +93,11 @@ Lines mapping:
51 <-> 31
53 <-> 34
55 <-> 36
56 <-> 39
57 <-> 39
Not mapped:
25
28
32
35
52
56
57
@@ -35,6 +35,7 @@ import java.util.List;
public class ResourceBundleImpl extends ResourceBundle {
@NotNull private final PropertiesFile myDefaultPropertiesFile;
private boolean myValid = true;
public ResourceBundleImpl(@NotNull final PropertiesFile defaultPropertiesFile) {
myDefaultPropertiesFile = defaultPropertiesFile;
@@ -94,6 +95,14 @@ public class ResourceBundleImpl extends ResourceBundle {
return myDefaultPropertiesFile.getProject();
}
public boolean isValid() {
return myValid;
}
public void invalidate() {
myValid = false;
}
public boolean equals(final Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
@@ -215,6 +215,9 @@ public class ResourceBundleManager implements PersistentStateComponent<ResourceB
LOG.assertTrue(state != null);
myState.getCustomResourceBundles().remove(state);
} else {
if (EmptyResourceBundle.getInstance() != resourceBundle) {
((ResourceBundleImpl) resourceBundle).invalidate();
}
for (final PropertiesFile propertiesFile : resourceBundle.getPropertiesFiles()) {
final VirtualFile file = propertiesFile.getContainingFile().getVirtualFile();
myState.getDissociatedFiles().add(file.getUrl());
@@ -26,6 +26,7 @@ import com.intellij.ide.projectView.ViewSettings;
import com.intellij.ide.projectView.impl.nodes.PsiFileNode;
import com.intellij.ide.util.treeView.AbstractTreeNode;
import com.intellij.lang.properties.*;
import com.intellij.lang.properties.ResourceBundle;
import com.intellij.lang.properties.editor.ResourceBundleAsVirtualFile;
import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.openapi.fileEditor.FileEditorManager;
@@ -104,6 +105,11 @@ public class ResourceBundleNode extends ProjectViewNode<ResourceBundle>{
if (!super.validate()) {
return false;
}
return Comparing.equal(getValue().getDefaultPropertiesFile().getResourceBundle(), getValue());
final ResourceBundle newBundle = getValue().getDefaultPropertiesFile().getResourceBundle();
final ResourceBundle currentBundle = getValue();
if (!Comparing.equal(newBundle, currentBundle)) {
return false;
}
return !(currentBundle instanceof ResourceBundleImpl) || ((ResourceBundleImpl)currentBundle).isValid();
}
}
@@ -82,7 +82,7 @@ public class PyCCEduProjectTemplate extends EduProjectTemplate {
StartupManager.getInstance(project).runWhenProjectIsInitialized(new Runnable() {
@Override
public void run() {
PyCCProjectGenerator.generateProject(project, baseDir, panel.getName(), panel.getAuthor(), panel.getDescription());
PyCCProjectGenerator.generateProject(project, baseDir, panel.getName(), panel.getAuthors(), panel.getDescription());
}
});
}
@@ -55,17 +55,17 @@ public class PyCCProjectGenerator extends PythonProjectGenerator implements Dire
public void generateProject(@NotNull final Project project, @NotNull final VirtualFile baseDir,
@Nullable Object settings, @NotNull Module module) {
generateProject(project, baseDir, mySettingsPanel.getName(),
mySettingsPanel.getAuthor(), mySettingsPanel.getDescription());
mySettingsPanel.getAuthors(), mySettingsPanel.getDescription());
}
public static void generateProject(@NotNull final Project project, @NotNull final VirtualFile baseDir,
@NotNull final String name, @NotNull final String author,
@NotNull final String name, @NotNull final String[] authors,
@NotNull final String description) {
final CCProjectService service = CCProjectService.getInstance(project);
final Course course = new Course();
course.setName(name);
course.setAuthor(author);
course.setAuthors(authors);
course.setDescription(description);
course.setLanguage("Python");
service.setCourse(course);
@@ -93,7 +93,7 @@ public class PyCCProjectGenerator extends PythonProjectGenerator implements Dire
public ValidationResult validate(@NotNull String s) {
String message = "";
message = mySettingsPanel.getDescription().isEmpty() ? "Enter description" : message;
message = mySettingsPanel.getAuthor().isEmpty() ? "Enter author name" : message;
message = mySettingsPanel.getAuthors().length == 0 ? "Enter author name" : message;
message = mySettingsPanel.getName().isEmpty() ? "Enter course name" : message;
return message.isEmpty() ? ValidationResult.OK : new ValidationResult(message);
}
@@ -102,7 +102,7 @@ public class PyStudyDirectoryProjectGenerator extends PythonProjectGenerator imp
}
public List<CourseInfo> getCourses() {
return myGenerator.getCourses();
return myGenerator.getCourses(false);
}
public void setSelectedCourse(CourseInfo course) {
@@ -78,12 +78,12 @@ public class CCChangeCourseInfo extends DumbAwareAction {
if (directory != null && !project.getBaseDir().equals(directory.getVirtualFile())) {
return;
}
CCNewProjectPanel panel = new CCNewProjectPanel(course.getName(), course.getAuthor(), course.getDescription());
CCNewProjectPanel panel = new CCNewProjectPanel(course.getName(), Course.getAuthorsString(course.getAuthors()), course.getDescription());
ChangeCourseInfoDialog changeCourseInfoDialog =
new ChangeCourseInfoDialog(project, panel);
changeCourseInfoDialog.show();
if (changeCourseInfoDialog.getExitCode() == DialogWrapper.OK_EXIT_CODE) {
course.setAuthor(panel.getAuthor());
course.setAuthors(panel.getAuthors());
course.setName(panel.getName());
course.setDescription(panel.getDescription());
ProjectView.getInstance(project).refresh();
@@ -35,7 +35,7 @@ public class CCPushLesson extends DumbAwareAction {
if (course == null) {
return;
}
PsiDirectory lessonDir = DirectoryChooserUtil.getOrChooseDirectory(view);;
PsiDirectory lessonDir = DirectoryChooserUtil.getOrChooseDirectory(view);
if (lessonDir == null || !lessonDir.getName().contains("lesson")) {
return;
}
@@ -51,8 +51,8 @@ public class CCNewProjectPanel {
}
@NotNull
public String getAuthor() {
return StringUtil.notNullize(myAuthorField.getText());
public String[] getAuthors() {
return StringUtil.splitByLines(StringUtil.notNullize(myAuthorField.getText()));
}
public void registerValidators(FacetValidatorsManager manager) {
@@ -211,10 +211,13 @@ public class StudyProjectGenerator {
}
writer = new PrintWriter(cashFile);
for (CourseInfo courseInfo : myCourses) {
String line = String
.format("name=%s author=%s description=%s", courseInfo.getName(), courseInfo.getAuthor(),
courseInfo.getDescription());
writer.println(line);
final List<CourseInfo.Instructor> instructors = courseInfo.getInstructors();
StringBuilder builder = new StringBuilder("name=").append(courseInfo.getName()).append("description=").append(
courseInfo.getDescription());
for (CourseInfo.Instructor instructor : instructors) {
builder.append("instructor=").append(instructor.getName());
}
writer.println(builder.toString());
}
}
catch (FileNotFoundException e) {
@@ -228,12 +231,12 @@ public class StudyProjectGenerator {
}
}
public List<CourseInfo> getCourses() {
if (!myCourses.isEmpty()) {
public List<CourseInfo> getCourses(boolean force) {
if (force || myCourses.isEmpty()) {
myCourses = EduStepicConnector.getCourses();
return myCourses;
}
else {
myCourses = EduStepicConnector.getCourses();
return myCourses;
}
}
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.jetbrains.edu.learning.ui.StudyNewProjectPanel">
<grid id="27dc6" binding="myContentPanel" layout-manager="GridLayoutManager" row-count="2" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="27dc6" binding="myContentPanel" layout-manager="GridLayoutManager" row-count="4" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
@@ -67,6 +67,72 @@
<verticalTextPosition value="1"/>
</properties>
</component>
<grid id="f583f" binding="myHideablePanel" layout-manager="BorderLayout" hgap="0" vgap="0">
<constraints>
<grid row="3" column="1" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<grid id="b4a52" binding="myLoginPanel" layout-manager="GridBagLayout">
<constraints border-constraint="Center"/>
<properties/>
<border type="none"/>
<children>
<component id="f0dd0" class="javax.swing.JPasswordField" binding="myPasswordField">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
<gridbag weightx="1.0" weighty="1.0"/>
</constraints>
<properties/>
</component>
<component id="8d976" class="javax.swing.JLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
<gridbag weightx="0.0" weighty="1.0"/>
</constraints>
<properties>
<text value="Password:"/>
</properties>
</component>
<component id="56bf1" class="javax.swing.JTextField" binding="myLoginField">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
<gridbag weightx="1.0" weighty="1.0"/>
</constraints>
<properties/>
</component>
<component id="fb0e2" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
<gridbag weightx="0.0" weighty="1.0"/>
</constraints>
<properties>
<text value="E-mail:"/>
</properties>
</component>
<component id="5f574" class="javax.swing.JButton" binding="myLogInButton" default-binding="true">
<constraints>
<grid row="0" column="2" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
<gridbag weightx="0.0" weighty="1.0"/>
</constraints>
<properties>
<text value="Log in"/>
</properties>
</component>
</children>
</grid>
</children>
</grid>
<vspacer id="9a0a">
<constraints>
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
</children>
</grid>
</form>
@@ -3,9 +3,12 @@ package com.jetbrains.edu.learning.ui;
import com.intellij.facet.ui.FacetValidatorsManager;
import com.intellij.facet.ui.ValidationResult;
import com.intellij.icons.AllIcons;
import com.intellij.ui.HideableDecorator;
import com.jetbrains.edu.courseFormat.Course;
import com.jetbrains.edu.learning.StudyUtils;
import com.jetbrains.edu.learning.courseGeneration.StudyProjectGenerator;
import com.jetbrains.edu.stepic.CourseInfo;
import com.jetbrains.edu.stepic.EduStepicConnector;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
@@ -19,6 +22,7 @@ import java.util.List;
* data: 7/31/14.
*/
public class StudyNewProjectPanel{
private final HideableDecorator myDecorator;
private List<CourseInfo> myAvailableCourses = new ArrayList<CourseInfo>();
private JComboBox myCoursesComboBox;
private JButton myRefreshButton;
@@ -27,6 +31,11 @@ public class StudyNewProjectPanel{
private JLabel myDescriptionLabel;
private JLabel myLabel;
private JPanel myInfoPanel;
private JPanel myHideablePanel;
private JPanel myLoginPanel;
private JPasswordField myPasswordField;
private JTextField myLoginField;
private JButton myLogInButton;
private final StudyProjectGenerator myGenerator;
private static final String CONNECTION_ERROR = "<html>Failed to download courses.<br>Check your Internet connection.</html>";
private static final String INVALID_COURSE = "Selected course is invalid";
@@ -34,7 +43,7 @@ public class StudyNewProjectPanel{
public StudyNewProjectPanel(StudyProjectGenerator generator) {
myGenerator = generator;
myAvailableCourses = myGenerator.getCourses();
myAvailableCourses = myGenerator.getCourses(false);
if (myAvailableCourses.isEmpty()) {
setError(CONNECTION_ERROR);
}
@@ -42,7 +51,7 @@ public class StudyNewProjectPanel{
for (CourseInfo courseInfo : myAvailableCourses) {
myCoursesComboBox.addItem(courseInfo);
}
myAuthorLabel.setText("Author: " + StudyUtils.getFirst(myAvailableCourses).getAuthor());
myAuthorLabel.setText("Author: " + Course.getAuthorsString(StudyUtils.getFirst(myAvailableCourses).getInstructors()));
myDescriptionLabel.setText(StudyUtils.getFirst(myAvailableCourses).getDescription());
//setting the first course in list as selected
myGenerator.setSelectedCourse(StudyUtils.getFirst(myAvailableCourses));
@@ -53,12 +62,26 @@ public class StudyNewProjectPanel{
myRefreshButton.setIcon(AllIcons.Actions.Refresh);
myLabel.setPreferredSize(new JLabel("Project name").getPreferredSize());
myDecorator = new HideableDecorator(myHideablePanel, "Credentials", false);
myDecorator.setOn(false);
myDecorator.setContentComponent(myLoginPanel);
}
private void initListeners() {
myRefreshButton.addActionListener(new RefreshActionListener());
myCoursesComboBox.addActionListener(new CourseSelectedListener());
myLogInButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
final boolean isSuccess = EduStepicConnector.login(myLoginField.getText(), String.valueOf(myPasswordField.getPassword()));
if (!isSuccess) {
setError("Failed to log in");
return;
}
refreshCoursesList();
}
});
}
private void setError(@NotNull final String errorMessage) {
@@ -92,24 +115,28 @@ public class StudyNewProjectPanel{
private class RefreshActionListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
final List<CourseInfo> courses = myGenerator.getCourses();
if (courses.isEmpty()) {
setError(CONNECTION_ERROR);
return;
}
myCoursesComboBox.removeAllItems();
for (CourseInfo courseInfo : courses) {
myCoursesComboBox.addItem(courseInfo);
}
myGenerator.setSelectedCourse(StudyUtils.getFirst(courses));
myGenerator.setCourses(courses);
myAvailableCourses = courses;
myGenerator.flushCache();
refreshCoursesList();
}
}
private void refreshCoursesList() {
final List<CourseInfo> courses = myGenerator.getCourses(true);
if (courses.isEmpty()) {
setError(CONNECTION_ERROR);
return;
}
myCoursesComboBox.removeAllItems();
for (CourseInfo courseInfo : courses) {
myCoursesComboBox.addItem(courseInfo);
}
myGenerator.setSelectedCourse(StudyUtils.getFirst(courses));
myGenerator.setCourses(courses);
myAvailableCourses = courses;
myGenerator.flushCache();
}
/**
* Handles selecting course in combo box
@@ -126,7 +153,7 @@ public class StudyNewProjectPanel{
myDescriptionLabel.setText("");
return;
}
myAuthorLabel.setText("Author: " + selectedCourse.getAuthor());
myAuthorLabel.setText("Author: " + Course.getAuthorsString(selectedCourse.getInstructors()));
myCoursesComboBox.removeItem(CourseInfo.INVALID_COURSE);
myDescriptionLabel.setText(selectedCourse.getDescription());
myGenerator.setSelectedCourse(selectedCourse);
@@ -36,8 +36,7 @@ public class StudyToolWindowFactory implements ToolWindowFactory, DumbAware {
}
String courseName = UIUtil.toHtml("<h1>" + course.getName() + "</h1>", 10);
String description = UIUtil.toHtml(course.getDescription(), 5);
String author = taskManager.getCourse().getAuthor();
String authorLabel = UIUtil.toHtml("<b>Author: </b>" + author, 5);
String authorLabel = UIUtil.toHtml("<b>Author: </b>" + Course.getAuthorsString(course.getAuthors()), 5);
contentPanel.add(new JLabel(courseName));
contentPanel.add(new JLabel(authorLabel));
contentPanel.add(Box.createRigidArea(new Dimension(0, 10)));
@@ -3,8 +3,11 @@ package com.jetbrains.edu.courseFormat;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import com.intellij.lang.Language;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Function;
import com.jetbrains.edu.EduNames;
import com.jetbrains.edu.EduUtils;
import com.jetbrains.edu.stepic.CourseInfo;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
@@ -17,7 +20,7 @@ public class Course {
@Expose private String description;
@Expose private String name;
private String myCourseDirectory = "";
@Expose private String author="";
@Expose private List<CourseInfo.Instructor> authors = new ArrayList<CourseInfo.Instructor>();
private boolean myUpToDate;
@Expose @SerializedName("language")
@@ -56,12 +59,25 @@ public class Course {
return lessons.get(lessonIndex);
}
public String getAuthor() {
return author;
@NotNull
public List<CourseInfo.Instructor> getAuthors() {
return authors;
}
public void setAuthor(String author) {
this.author = author;
public static String getAuthorsString(@NotNull List<CourseInfo.Instructor> authors) {
return StringUtil.join(authors, new Function<CourseInfo.Instructor, String>() {
@Override
public String fun(CourseInfo.Instructor instructor) {
return instructor.getName();
}
}, ", ");
}
public void setAuthors(String[] authors) {
this.authors = new ArrayList<CourseInfo.Instructor>();
for (String name : authors) {
this.authors.add(new CourseInfo.Instructor(name));
}
}
public String getName() {
@@ -107,4 +123,8 @@ public class Course {
public void setLanguage(@NotNull final String language) {
myLanguage = language;
}
public void setAuthors(List<CourseInfo.Instructor> instructors) {
this.authors = instructors;
}
}
@@ -1,7 +1,9 @@
package com.jetbrains.edu.stepic;
import com.google.gson.annotations.SerializedName;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
/**
@@ -19,22 +21,18 @@ public class CourseInfo {
//course type in format "pycharm <language>"
private String myType;
private String myAuthor;
public static CourseInfo INVALID_COURSE = new CourseInfo("", "", "", "");
@SerializedName("instructors")
List<Instructor> myInstructors = new ArrayList<Instructor>();
public CourseInfo(String name, String author, String description, String type) {
myName = name;
myAuthor = author;
myDescription = description;
myType = type;
}
public static CourseInfo INVALID_COURSE = new CourseInfo();
public String getName() {
return myName;
}
public String getAuthor() {
return myAuthor;
@NotNull
public List<Instructor> getInstructors() {
return myInstructors;
}
public String getDescription() {
@@ -55,15 +53,27 @@ public class CourseInfo {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
CourseInfo that = (CourseInfo)o;
return that.getName().equals(myName) && that.getAuthor().equals(myAuthor)
if (that.getName() == null || that.getDescription() == null) return false;
return that.getName().equals(myName)
&& that.getDescription().equals(myDescription);
}
@Override
public int hashCode() {
int result = myName != null ? myName.hashCode() : 0;
result = 31 * result + (myAuthor != null ? myAuthor.hashCode() : 0);
result = 31 * result + (myDescription != null ? myDescription.hashCode() : 0);
return result;
}
public static class Instructor {
String name;
public Instructor(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
}
@@ -8,89 +8,164 @@ import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.io.HttpRequests;
import com.intellij.util.net.ssl.CertificateManager;
import com.jetbrains.edu.EduUtils;
import com.jetbrains.edu.courseFormat.Course;
import com.jetbrains.edu.courseFormat.Lesson;
import com.jetbrains.edu.courseFormat.Task;
import com.jetbrains.edu.courseFormat.TaskFile;
import org.apache.http.Header;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.cookie.Cookie;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.jetbrains.annotations.NotNull;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.*;
public class EduStepicConnector {
private static final String stepicApiUrl = "https://stepic.org/api/";
private static final String stepicUrl = "https://stepic.org/";
private static final String stepicApiUrl = stepicUrl + "api/";
private static final Logger LOG = Logger.getInstance(EduStepicConnector.class.getName());
private static final String ourDomain = "stepic.org";
private static String ourSessionId = "524iethiwju2tjywaqmf7tbwx0p0jk1b";
private static String ourCSRFToken = "LJ9n6OyLVA7hxU94dlYWUu65MF51Nx37";
private static String ourCSRFToken = "";
private static CloseableHttpClient ourClient;
//this prefix indicates that course can be opened by educational plugin
public static final String PYCHARM_PREFIX = "pycharm ";
public static final String PYCHARM_PREFIX = "pycharm";
private static BasicCookieStore ourCookieStore;
private EduStepicConnector() {
}
private static <T> T getFromStepic(String link, final Class<T> container) throws IOException {
return HttpRequests.request(stepicApiUrl + link).connect(new HttpRequests.RequestProcessor<T>() {
@Override
public T process(@NotNull HttpRequests.Request request) throws IOException {
final BufferedReader reader = request.getReader();
Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
return gson.fromJson(reader, container);
public static boolean login(@NotNull final String user, @NotNull final String password) {
if (ourClient == null || ourCookieStore == null)
initializeClient();
return postCredentials(user, password);
}
private static void initializeClient() {
final HttpGet request = new HttpGet(stepicUrl);
request.addHeader(new BasicHeader("referer", "https://stepic.org"));
request.addHeader(new BasicHeader("content-type", "application/json"));
HttpClientBuilder builder = HttpClients.custom().setSslcontext(CertificateManager.getInstance().getSslContext()).setMaxConnPerRoute(100);
ourCookieStore = new BasicCookieStore();
ourClient = builder.setDefaultCookieStore(ourCookieStore).build();
try {
ourClient.execute(request);
saveCSRFToken();
}
catch (IOException e) {
LOG.error(e.getMessage());
}
}
private static void saveCSRFToken() {
if (ourCookieStore == null) return;
final List<Cookie> cookies = ourCookieStore.getCookies();
for (Cookie cookie : cookies) {
if (cookie.getName().equals("csrftoken")) {
ourCSRFToken = cookie.getValue();
}
});
}
}
private static boolean postCredentials(String user, String password) {
String url = stepicUrl + "accounts/login/";
final HttpPost request = new HttpPost(url);
List <NameValuePair> nvps = new ArrayList <NameValuePair>();
nvps.add(new BasicNameValuePair("csrfmiddlewaretoken", ourCSRFToken));
nvps.add(new BasicNameValuePair("login", user));
nvps.add(new BasicNameValuePair("next", "/"));
nvps.add(new BasicNameValuePair("password", password));
nvps.add(new BasicNameValuePair("remember", "on"));
try {
request.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
}
catch (UnsupportedEncodingException e) {
LOG.error(e.getMessage());
return false;
}
setHeaders(request, "application/x-www-form-urlencoded");
try {
final CloseableHttpResponse response = ourClient.execute(request);
saveCSRFToken();
final StatusLine line = response.getStatusLine();
if (line.getStatusCode() != 302) {
LOG.error("Failed to login " + EntityUtils.toString(response.getEntity()));
return false;
}
}
catch (IOException e) {
LOG.error(e.getMessage());
return false;
}
return true;
}
private static <T> T getFromStepic(String link, final Class<T> container) throws IOException {
final HttpGet request = new HttpGet(stepicApiUrl + link);
if (ourClient == null) {
initializeClient();
}
setHeaders(request, "application/json");
final CloseableHttpResponse response = ourClient.execute(request);
final String responseString = EntityUtils.toString(response.getEntity());
Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
return gson.fromJson(responseString, container);
}
@NotNull
public static List<CourseInfo> getCourses() {
try {
return getFromStepic("courses/99", CoursesContainer.class).courses;
List<CourseInfo> result = new ArrayList<CourseInfo>();
final List<CourseInfo> courseInfos = getFromStepic("courses", CoursesContainer.class).courses;
for (CourseInfo info : courseInfos) {
final String courseType = info.getType();
if (StringUtil.isEmptyOrSpaces(courseType)) continue;
final List<String> typeLanguage = StringUtil.split(courseType, " ");
if (typeLanguage.size() == 2 && PYCHARM_PREFIX.equals(typeLanguage.get(0))) {
result.add(info);
}
}
return result;
}
catch (IOException e) {
LOG.error("IOException " + e.getMessage());
LOG.error("Cannot load course list " + e.getMessage());
}
return Collections.emptyList();
/*try { // TODO: uncomment
return HttpRequests.request(stepicApiUrl + "courses").connect(new HttpRequests.RequestProcessor<List<CourseInfo>>() {
@Override
public List<CourseInfo> process(@NotNull HttpRequests.Request request) throws IOException {
final BufferedReader reader = request.getReader();
Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create();
return gson.fromJson(reader, CoursesContainer.class).courses;
}
});
}
catch (IOException e) {
LOG.error("IOException " + e.getMessage());
}
return null;*/
}
public static Course getCourse(@NotNull final CourseInfo info) {
final Course course = new Course();
course.setAuthor(info.getAuthor());
course.setAuthors(info.getInstructors());
course.setDescription(info.getDescription());
course.setName(info.getName());
String courseType = info.getType();
course.setLanguage(courseType.substring(PYCHARM_PREFIX.length()));
course.setLanguage(courseType.substring(PYCHARM_PREFIX.length() + 1));
course.setUpToDate(true); // TODO: get from stepic
try {
for (Integer section : info.sections) {
@@ -128,7 +203,7 @@ public class EduStepicConnector {
private static void createTask(Lesson lesson, Integer s) throws IOException {
final Step step = getStep(s);
final Task task = new Task();
task.setName(step.name);
task.setName(step.options != null ? step.options.title : PYCHARM_PREFIX);
task.setText(step.text);
for (TestFileWrapper wrapper : step.options.test) {
task.setTestsTexts(wrapper.name, wrapper.text);
@@ -148,23 +223,29 @@ public class EduStepicConnector {
}
public static boolean postLesson(Project project, @NotNull final Lesson lesson) {
final HttpPost request = new HttpPost(stepicApiUrl + "lessons");
final ArrayList<Header> headers = getHeaders(request);
HttpClientBuilder builder = HttpClients.custom().setSslcontext(CertificateManager.getInstance().getSslContext());
final BasicCookieStore cookieStore = getCookies();
final CloseableHttpClient client = builder.setDefaultHeaders(headers).setDefaultCookieStore(cookieStore).build();
public static void showLoginDialog() {
final LoginDialog dialog = new LoginDialog();
dialog.show();
}
public static void postLesson(Project project, @NotNull final Lesson lesson) {
final HttpPost request = new HttpPost(stepicApiUrl + "lessons");
if (ourClient == null) {
showLoginDialog();
}
setHeaders(request, "application/json");
String requestBody = new Gson().toJson(new LessonWrapper(lesson));
request.setEntity(new StringEntity(requestBody, ContentType.APPLICATION_JSON));
try {
final CloseableHttpResponse response = client.execute(request);
final CloseableHttpResponse response = ourClient.execute(request);
final String responseString = EntityUtils.toString(response.getEntity());
final StatusLine line = response.getStatusLine();
if (line.getStatusCode() != 201) {
LOG.error("Failed to push " + EntityUtils.toString(response.getEntity()));
return false;
LOG.error("Failed to push " + responseString);
return;
}
final Lesson postedLesson = new Gson().fromJson(responseString, Course.class).getLessons().get(0);
for (Task task : lesson.getTaskList()) {
@@ -174,56 +255,31 @@ public class EduStepicConnector {
catch (IOException e) {
LOG.error(e.getMessage());
}
return false;
}
public static boolean postTask(Project project, @NotNull final Task task, int id) {
public static void postTask(Project project, @NotNull final Task task, int id) {
final HttpPost request = new HttpPost(stepicApiUrl + "step-sources");
final ArrayList<Header> headers = getHeaders(request);
HttpClientBuilder builder = HttpClients.custom().setSslcontext(CertificateManager.getInstance().getSslContext());
final BasicCookieStore cookieStore = getCookies();
final CloseableHttpClient client = builder.setDefaultHeaders(headers).setDefaultCookieStore(cookieStore).build();
setHeaders(request, "application/json");
final Gson gson = new GsonBuilder().setPrettyPrinting().excludeFieldsWithoutExposeAnnotation().create();
String requestBody = gson.toJson(new StepSourceWrapper(project, task, id));
request.setEntity(new StringEntity(requestBody, ContentType.APPLICATION_JSON));
try {
final CloseableHttpResponse response = client.execute(request);
final CloseableHttpResponse response = ourClient.execute(request);
final StatusLine line = response.getStatusLine();
if (line.getStatusCode() != 201) {
LOG.error("Failed to push " + EntityUtils.toString(response.getEntity()));
}
return line.getStatusCode() == 201;
}
catch (IOException e) {
LOG.error(e.getMessage());
}
return false;
}
private static BasicCookieStore getCookies() {
final BasicCookieStore cookieStore = new BasicCookieStore();
final BasicClientCookie sessionid = new BasicClientCookie("sessionid", ourSessionId);
sessionid.setDomain(ourDomain);
sessionid.setPath("/");
cookieStore.addCookie(sessionid);
final BasicClientCookie csrfToken = new BasicClientCookie("csrftoken", ourCSRFToken);
csrfToken.setDomain(ourDomain);
csrfToken.setPath("/");
cookieStore.addCookie(csrfToken);
return cookieStore;
}
private static ArrayList<Header> getHeaders(HttpPost request) {
final ArrayList<Header> headers = new ArrayList<Header>();
headers.add(new BasicHeader("referer", "https://stepic.org"));
headers.add(new BasicHeader("X-CSRFToken", ourCSRFToken));
headers.add(new BasicHeader("content-type", "application/json"));
request.setHeaders(headers.toArray(new Header[headers.size()]));
return headers;
private static void setHeaders(@NotNull final HttpRequestBase request, String contentType) {
request.addHeader(new BasicHeader("referer", stepicUrl));
request.addHeader(new BasicHeader("X-CSRFToken", ourCSRFToken));
request.addHeader(new BasicHeader("content-type", contentType));
}
private static class StepContainer {
@@ -262,6 +318,7 @@ public class EduStepicConnector {
@Override
public void run() {
final VirtualFile taskDir = task.getTaskDir(project);
assert taskDir != null;
EduUtils.createStudentFileFromAnswer(project, taskDir, taskDir, entry);
}
});
@@ -0,0 +1,62 @@
package com.jetbrains.edu.stepic;
import com.intellij.openapi.ui.DialogWrapper;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
public class LoginDialog extends DialogWrapper {
private final LoginPanel myLoginPanel;
public LoginDialog() {
super(false);
myLoginPanel = new LoginPanel(this);
setTitle("Login to Stepic");
setOKButtonText("Login");
init();
}
@NotNull
protected Action[] createActions() {
return new Action[]{getOKAction(), getCancelAction()};
}
@Override
protected JComponent createCenterPanel() {
return myLoginPanel.getPanel();
}
@Override
protected String getHelpId() {
return "login_to_stepic";
}
@Override
public JComponent getPreferredFocusedComponent() {
return myLoginPanel.getPreferableFocusComponent();
}
@Override
protected void doOKAction() {
AuthDataHolder authData = myLoginPanel.getAuthData();
final boolean success = EduStepicConnector.login(authData.email, authData.password);
if (!success) {
setErrorText("Log in failed");
}
super.doOKAction();
}
public void clearErrors() {
setErrorText(null);
}
public static class AuthDataHolder {
String email;
String password;
public AuthDataHolder(String login, String password) {
email = login;
this.password = password;
}
}
}
@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.jetbrains.edu.stepic.LoginPanel">
<grid id="27dc6" binding="myPane" layout-manager="GridLayoutManager" row-count="3" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="174"/>
</constraints>
<properties>
<focusable value="false"/>
</properties>
<border type="none"/>
<children>
<vspacer id="9b306">
<constraints>
<grid row="2" 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="9edbd" class="javax.swing.JPasswordField" binding="myPasswordField">
<constraints>
<grid row="1" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="300" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="fe9db" class="javax.swing.JLabel">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Password:"/>
</properties>
</component>
<component id="e76ec" class="javax.swing.JTextField" binding="myLoginTextField">
<constraints>
<grid row="0" column="1" row-span="1" col-span="2" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties/>
</component>
<component id="c0234" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="E-mail:"/>
</properties>
</component>
</children>
</grid>
</form>
@@ -0,0 +1,69 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jetbrains.edu.stepic;
import com.intellij.ui.DocumentAdapter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
public class LoginPanel {
private JPanel myPane;
private JTextField myLoginTextField;
private JPasswordField myPasswordField;
public LoginPanel(final LoginDialog dialog) {
DocumentListener listener = new DocumentAdapter() {
@Override
protected void textChanged(DocumentEvent e) {
dialog.clearErrors();
}
};
myLoginTextField.getDocument().addDocumentListener(listener);
myPasswordField.getDocument().addDocumentListener(listener);
}
public JComponent getPanel() {
return myPane;
}
public void setLogin(@Nullable String login) {
myLoginTextField.setText(login);
}
@NotNull
public String getLogin() {
return myLoginTextField.getText().trim();
}
@NotNull
private String getPassword() {
return String.valueOf(myPasswordField.getPassword());
}
public JComponent getPreferableFocusComponent() {
return myLoginTextField.isVisible() ? myLoginTextField : myPasswordField;
}
@NotNull
public LoginDialog.AuthDataHolder getAuthData() {
return new LoginDialog.AuthDataHolder(getLogin(), getPassword());
}
}
+9 -2
View File
@@ -95,18 +95,25 @@ def _excepthook(exctype, value, tb):
return
frames = []
debugger = GetGlobalDebugger()
user_frames = []
while tb:
frame = tb.tb_frame
if exception_breakpoint.ignore_libraries and not debugger.not_in_scope(frame.f_code.co_filename):
user_frames.append(tb.tb_frame)
frames.append(tb.tb_frame)
tb = tb.tb_next
thread = threadingCurrentThread()
frames_byid = dict([(id(frame),frame) for frame in frames])
frame = frames[-1]
if exception_breakpoint.ignore_libraries:
frame = user_frames[-1]
else:
frame = frames[-1]
thread.additionalInfo.exception = (exctype, value, tb)
thread.additionalInfo.pydev_force_stop_at_exception = (frame, frames_byid)
thread.additionalInfo.message = exception_breakpoint.qname
debugger = GetGlobalDebugger()
pydevd_tracing.SetTrace(None) #no tracing from here
File diff suppressed because one or more lines are too long
@@ -15,11 +15,14 @@
*/
package com.jetbrains.python.psi;
import com.google.common.collect.ImmutableList;
import com.intellij.openapi.util.Key;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* @author yole
*/
@@ -35,6 +38,19 @@ public enum LanguageLevel {
PYTHON34(34, true, false, true, true),
PYTHON35(35, true, false, true, true);
public static List<LanguageLevel> ALL_LEVELS = ImmutableList.<LanguageLevel>builder()
.add(PYTHON24)
.add(PYTHON25)
.add(PYTHON26)
.add(PYTHON27)
.add(PYTHON30)
.add(PYTHON31)
.add(PYTHON32)
.add(PYTHON33)
.add(PYTHON34)
.add(PYTHON35)
.build();
private static LanguageLevel DEFAULT2 = PYTHON27;
private static LanguageLevel DEFAULT3 = PYTHON34;
@@ -15,12 +15,15 @@
*/
package com.jetbrains.numpy.codeInsight;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.jetbrains.numpy.documentation.NumPyDocString;
import com.jetbrains.numpy.documentation.NumPyDocStringParameter;
import com.jetbrains.python.psi.*;
import com.jetbrains.python.psi.impl.PyBuiltinCache;
import com.jetbrains.python.psi.impl.PyExpressionCodeFragmentImpl;
import com.jetbrains.python.psi.types.PyType;
import com.jetbrains.python.psi.types.PyTypeProviderBase;
import com.jetbrains.python.psi.types.TypeEvalContext;
@@ -47,6 +50,7 @@ public class NumpyDocStringTypeProvider extends PyTypeProviderBase {
// an instance of 'numpy.core.multiarray.dtype', however the type checker isn't able to check it.
// 30 occurrences
NUMPY_ALIAS_TO_REAL_TYPE.put("data-type", "object");
NUMPY_ALIAS_TO_REAL_TYPE.put("dtype", "object");
// 16 occurrences
NUMPY_ALIAS_TO_REAL_TYPE.put("scalar", "int or long or float or complex");
// 10 occurrences
@@ -62,6 +66,8 @@ public class NumpyDocStringTypeProvider extends PyTypeProviderBase {
NUMPY_ALIAS_TO_REAL_TYPE.put("callable", "collections.Callable");
// 3 occurrences
NUMPY_ALIAS_TO_REAL_TYPE.put("number", "int or long or float or complex");
NUMPY_ALIAS_TO_REAL_TYPE.put("sequence", "collections.Iterable");
}
@Nullable
@@ -111,6 +117,7 @@ public class NumpyDocStringTypeProvider extends PyTypeProviderBase {
}
private static boolean isInsideNumPy(@NotNull PsiElement element) {
if (ApplicationManager.getApplication().isUnitTestMode()) return true;
final PsiFile file = element.getContainingFile();
if (file != null) {
final PyPsiFacade facade = getPsiFacade(element);
@@ -137,7 +144,31 @@ public class NumpyDocStringTypeProvider extends PyTypeProviderBase {
return type;
}
}
return facade.parseTypeAnnotation(typeString, anchor);
final PyType type = facade.parseTypeAnnotation(typeString, anchor);
if (type != null) {
return type;
}
return getNominalType(anchor, typeString);
}
/**
* Converts literal into type, e.g. -1 -> int, 'fro' -> str
*/
@Nullable
private static PyType getNominalType(@NotNull PsiElement anchor, @NotNull String typeString) {
final PyExpressionCodeFragmentImpl codeFragment = new PyExpressionCodeFragmentImpl(anchor.getProject(), "dummy.py", typeString, false);
final PsiElement element = codeFragment.getFirstChild();
if (element instanceof PyExpressionStatement) {
final PyExpression expression = ((PyExpressionStatement)element).getExpression();
final PyBuiltinCache builtinCache = PyBuiltinCache.getInstance(anchor);
if (expression instanceof PyStringLiteralExpression) {
return builtinCache.getStrType();
}
if (expression instanceof PyNumericLiteralExpression) {
return builtinCache.getIntType();
}
}
return null;
}
@Nullable
@@ -154,7 +185,7 @@ public class NumpyDocStringTypeProvider extends PyTypeProviderBase {
}
@Nullable
private PyType getParameterType(@NotNull PyFunction function, @NotNull String parameterName) {
private static PyType getParameterType(@NotNull PyFunction function, @NotNull String parameterName) {
final NumPyDocString docString = NumPyDocString.forFunction(function, function);
if (docString != null) {
NumPyDocStringParameter parameter = docString.getNamedParameter(parameterName);
@@ -42,7 +42,7 @@ public class PyExceptionBreakpointProperties extends ExceptionBreakpointProperti
public PyExceptionBreakpointProperties(@NotNull final String exception) {
myException = exception;
myNotifyOnTerminate = true;
myIgnoreLibraries = true;
myIgnoreLibraries = false;
}
@Override
@@ -34,11 +34,9 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.profile.codeInspection.InspectionProfileManager;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiReference;
import com.intellij.psi.*;
import com.intellij.util.Function;
import com.jetbrains.python.codeInsight.imports.AddImportHelper;
import com.jetbrains.python.codeInsight.stdlib.PyStdlibUtil;
import com.jetbrains.python.packaging.*;
import com.jetbrains.python.packaging.ui.PyChooseRequirementsDialog;
@@ -362,6 +360,63 @@ public class PyPackageRequirementsInspection extends PyInspection {
}
}
public static class InstallAndImportQuickFix implements LocalQuickFix {
private final Sdk mySdk;
private final Module myModule;
private String myPackageName;
@Nullable private final String myAsName;
@NotNull private final SmartPsiElementPointer<PyElement> myNode;
public InstallAndImportQuickFix(@NotNull final String packageName,
@Nullable final String asName,
@NotNull final PyElement node) {
myPackageName = packageName;
myAsName = asName;
myNode = SmartPointerManager.getInstance(node.getProject()).createSmartPsiElementPointer(node, node.getContainingFile());
myModule = ModuleUtilCore.findModuleForPsiElement(node);
mySdk = PythonSdkType.findPythonSdk(myModule);
}
@NotNull
public String getName() {
return "Install and import package " + myPackageName;
}
@NotNull
public String getFamilyName() {
return "Install and import package " + myPackageName;
}
public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
final PyPackageManagerUI ui = new PyPackageManagerUI(project, mySdk, new UIListener(myModule) {
@Override
public void finished(List<ExecutionException> exceptions) {
super.finished(exceptions);
if (exceptions.isEmpty()) {
final PyElement element = myNode.getElement();
if (element == null) return;
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
@Override
public void run() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
AddImportHelper.addImportStatement(element.getContainingFile(), myPackageName, myAsName,
AddImportHelper.ImportPriority.THIRD_PARTY, element);
}
});
}
}, "Add import", "Add import");
}
}
});
ui.install(Collections.singletonList(new PyRequirement(myPackageName)), Collections.<String>emptyList());
}
}
private static class UIListener implements PyPackageManagerUI.Listener {
private final Module myModule;
@@ -25,6 +25,7 @@ import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.popup.PopupChooserBuilder;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.QualifiedName;
@@ -91,7 +92,7 @@ public class PyPep8NamingInspection extends PyInspection {
}
}
if (!LOWERCASE_REGEX.matcher(name).matches() && !name.startsWith("_")) {
registerProblem(expression, "Variable in function should be lowercase", new PyRenameElementQuickFix());
registerAndAddRenameQuickFix(expression, "Variable in function should be lowercase");
}
}
}
@@ -101,10 +102,17 @@ public class PyPep8NamingInspection extends PyInspection {
final String name = node.getName();
if (name == null) return;
if (!LOWERCASE_REGEX.matcher(name).matches()) {
registerProblem(node, "Argument name should be lowercase", new PyRenameElementQuickFix());
registerAndAddRenameQuickFix(node, "Argument name should be lowercase");
}
}
private void registerAndAddRenameQuickFix(@Nullable final PsiElement node, @NotNull final String name) {
if (getHolder() != null && getHolder().isOnTheFly())
registerProblem(node, name, new PyRenameElementQuickFix());
else
registerProblem(node, name);
}
@Override
public void visitPyFunction(PyFunction function) {
final PyClass containingClass = function.getContainingClass();
@@ -117,7 +125,10 @@ public class PyPep8NamingInspection extends PyInspection {
if (!LOWERCASE_REGEX.matcher(name).matches()) {
final ASTNode nameNode = function.getNameNode();
if (nameNode != null) {
final List<LocalQuickFix> quickFixes = Lists.<LocalQuickFix>newArrayList(new PyRenameElementQuickFix());
final List<LocalQuickFix> quickFixes = Lists.newArrayList();
if (getHolder() != null && getHolder().isOnTheFly())
quickFixes.add(new PyRenameElementQuickFix());
if (containingClass != null) {
quickFixes.add(new IgnoreBaseClassQuickFix(containingClass, myTypeEvalContext));
}
@@ -150,7 +161,7 @@ public class PyPep8NamingInspection extends PyInspection {
if (!MIXEDCASE_REGEX.matcher(name).matches()) {
final ASTNode nameNode = node.getNameNode();
if (nameNode != null) {
registerProblem(nameNode.getPsi(), "Class names should use CamelCase convention", new PyRenameElementQuickFix());
registerAndAddRenameQuickFix(nameNode.getPsi(), "Class names should use CamelCase convention");
}
}
}
@@ -165,19 +176,19 @@ public class PyPep8NamingInspection extends PyInspection {
if (asName == null || name == null) return;
if (UPPERCASE_REGEX.matcher(name).matches()) {
if (!UPPERCASE_REGEX.matcher(asName).matches()) {
registerProblem(node.getAsNameElement(), "Constant variable imported as non constant", new PyRenameElementQuickFix());
registerAndAddRenameQuickFix(node.getAsNameElement(), "Constant variable imported as non constant");
}
}
else if (LOWERCASE_REGEX.matcher(name).matches()) {
if (!LOWERCASE_REGEX.matcher(asName).matches()) {
registerProblem(node.getAsNameElement(), "Lowercase variable imported as non lowercase", new PyRenameElementQuickFix());
registerAndAddRenameQuickFix(node.getAsNameElement(), "Lowercase variable imported as non lowercase");
}
}
else if (LOWERCASE_REGEX.matcher(asName).matches()) {
registerProblem(node.getAsNameElement(), "CamelCase variable imported as lowercase", new PyRenameElementQuickFix());
registerAndAddRenameQuickFix(node.getAsNameElement(), "CamelCase variable imported as lowercase");
}
else if (UPPERCASE_REGEX.matcher(asName).matches()) {
registerProblem(node.getAsNameElement(), "CamelCase variable imported as constant", new PyRenameElementQuickFix());
registerAndAddRenameQuickFix(node.getAsNameElement(), "CamelCase variable imported as constant");
}
}
}
@@ -13,12 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jetbrains.python;
package com.jetbrains.python.inspections.quickfix;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.jetbrains.python.PyBundle;
import com.jetbrains.python.codeInsight.imports.AddImportHelper;
import com.jetbrains.python.psi.LanguageLevel;
import com.jetbrains.python.psi.PyElementGenerator;
@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.jetbrains.python.quickFixes;
package com.jetbrains.python.inspections.quickfix;
import com.intellij.codeInsight.intention.HighPriorityAction;
import com.intellij.codeInsight.intention.IntentionAction;
@@ -0,0 +1,27 @@
package com.jetbrains.python.inspections.unresolvedReference;
import java.util.HashMap;
import java.util.Map;
public class PyPackageAliasesProvider {
private PyPackageAliasesProvider() {
}
public static final Map<String, String> commonAliases = new HashMap<String, String>();
static {
commonAliases.put("np", "numpy");
commonAliases.put("pl", "pylab");
commonAliases.put("p", "pylab");
commonAliases.put("sp", "scipy");
commonAliases.put("pd", "pandas");
commonAliases.put("sym", "sympy");
commonAliases.put("sm", "statmodels");
commonAliases.put("nx", "networkx");
commonAliases.put("sk", "sklearn");
commonAliases.put("plt", "matplotlib.pyplot");
commonAliases.put("mpimg", "matplotlib.image");
commonAliases.put("mimg", "matplotlib.image");
}
}
@@ -68,6 +68,7 @@ import com.jetbrains.python.psi.types.*;
import com.jetbrains.python.sdk.PythonSdkType;
import com.jetbrains.python.sdk.skeletons.PySkeletonRefresher;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -302,12 +303,10 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
if (element instanceof PyReferenceOwner) {
final PyResolveContext resolveContext = PyResolveContext.noImplicits().withTypeEvalContext(myTypeEvalContext);
final PsiPolyVariantReference reference = ((PyReferenceOwner)element).getReference(resolveContext);
if (reference != null) {
final ResolveResult[] resolveResults = reference.multiResolve(false);
for (ResolveResult resolveResult : resolveResults) {
if (resolveResult instanceof ImportedResolveResult) {
myUsedImports.addAll(((ImportedResolveResult)resolveResult).getNameDefiners());
}
final ResolveResult[] resolveResults = reference.multiResolve(false);
for (ResolveResult resolveResult : resolveResults) {
if (resolveResult instanceof ImportedResolveResult) {
myUsedImports.addAll(((ImportedResolveResult)resolveResult).getNameDefiners());
}
}
}
@@ -571,11 +570,9 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
hl_type = ProblemHighlightType.LIKE_UNKNOWN_SYMBOL;
}
if (element != null) {
PyImportStatementBase importStatementBase = PsiTreeUtil.getParentOfType(element, PyImportStatementBase.class);
if ((importStatementBase != null) && GenerateBinaryStubsFix.isApplicable(importStatementBase)) {
actions.addAll(GenerateBinaryStubsFix.generateFixes(importStatementBase));
}
PyImportStatementBase importStatementBase = PsiTreeUtil.getParentOfType(element, PyImportStatementBase.class);
if ((importStatementBase != null) && GenerateBinaryStubsFix.isApplicable(importStatementBase)) {
actions.addAll(GenerateBinaryStubsFix.generateFixes(importStatementBase));
}
if (qualifiedNames.size() == 1) {
final QualifiedName qualifiedName = qualifiedNames.get(0);
@@ -873,6 +870,24 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
actions.add(importFix.forLocalImport());
}
}
else {
final String refName = (node instanceof PyQualifiedExpression) ? ((PyQualifiedExpression)node).getReferencedName() : node.getText();
if (refName == null) return;
final QualifiedName qname = QualifiedName.fromDottedString(refName);
final List<String> components = qname.getComponents();
if (!components.isEmpty()) {
final String packageName = components.get(0);
if (PyPIPackageUtil.INSTANCE.isInPyPI(packageName)) {
actions.add(new PyPackageRequirementsInspection.InstallAndImportQuickFix(packageName, packageName, node));
}
else {
final String packageAlias = PyPackageAliasesProvider.commonAliases.get(packageName);
if (packageAlias != null && PyPIPackageUtil.INSTANCE.isInPyPI(packageName)) {
actions.add(new PyPackageRequirementsInspection.InstallAndImportQuickFix(packageAlias, packageName, node));
}
}
}
}
}
private static boolean suppressHintForAutoImport(PyElement node, AutoImportQuickFix importFix) {
@@ -891,7 +906,7 @@ public class PyUnresolvedReferencesInspection extends PyInspection {
return false;
}
private void addCreateClassFix(String refText, PsiElement element, List<LocalQuickFix> actions) {
private void addCreateClassFix(@NonNls String refText, PsiElement element, List<LocalQuickFix> actions) {
if (refText.length() > 2 && Character.isUpperCase(refText.charAt(0)) && !refText.toUpperCase().equals(refText) &&
PsiTreeUtil.getParentOfType(element, PyImportStatementBase.class) == null) {
PsiElement anchor = element;
@@ -56,7 +56,7 @@ import com.jetbrains.python.codeInsight.imports.OptimizeImportsQuickFix;
import com.jetbrains.python.formatter.PyCodeStyleSettings;
import com.jetbrains.python.inspections.PyPep8Inspection;
import com.jetbrains.python.inspections.quickfix.ReformatFix;
import com.jetbrains.python.quickFixes.RemoveTrailingBlankLinesFix;
import com.jetbrains.python.inspections.quickfix.RemoveTrailingBlankLinesFix;
import com.jetbrains.python.sdk.PreferredSdkComparator;
import com.jetbrains.python.sdk.PySdkUtil;
import com.jetbrains.python.sdk.PythonSdkType;

Some files were not shown because too many files have changed in this diff Show More