diff --git a/bin/scripts/unix/idea.sh b/bin/scripts/unix/idea.sh index 0a2df34dd688..a2abafa31ac4 100755 --- a/bin/scripts/unix/idea.sh +++ b/bin/scripts/unix/idea.sh @@ -42,12 +42,27 @@ fi OS_TYPE=`"$UNAME" -s` +# --------------------------------------------------------------------- +# Ensure IDE_HOME points to the directory where the IDE is installed. +# --------------------------------------------------------------------- +SCRIPT_LOCATION=$0 +if [ -x "$READLINK" ]; then + while [ -L "$SCRIPT_LOCATION" ]; do + SCRIPT_LOCATION=`"$READLINK" -e "$SCRIPT_LOCATION"` + done +fi + +IDE_HOME=`dirname "$SCRIPT_LOCATION"`/.. +IDE_BIN_HOME=`dirname "$SCRIPT_LOCATION"` + # --------------------------------------------------------------------- # Locate a JDK installation directory which will be used to run the IDE. -# Try (in order): @@product_uc@@_JDK, JDK_HOME, JAVA_HOME, "java" in PATH. +# Try (in order): @@product_uc@@_JDK, ../jre, JDK_HOME, JAVA_HOME, "java" in PATH. # --------------------------------------------------------------------- if [ -n "$@@product_uc@@_JDK" -a -x "$@@product_uc@@_JDK/bin/java" ]; then JDK="$@@product_uc@@_JDK" +elif [ -x "$IDE_HOME/jre/bin/java" ] && "$IDE_HOME/jre/bin/java" -version > /dev/null 2>&1 ; then + JDK="$IDE_HOME/jre" elif [ -n "$JDK_HOME" -a -x "$JDK_HOME/bin/java" ]; then JDK="$JDK_HOME" elif [ -n "$JAVA_HOME" -a -x "$JAVA_HOME/bin/java" ]; then @@ -108,19 +123,6 @@ else BITS="" fi -# --------------------------------------------------------------------- -# Ensure IDE_HOME points to the directory where the IDE is installed. -# --------------------------------------------------------------------- -SCRIPT_LOCATION=$0 -if [ -x "$READLINK" ]; then - while [ -L "$SCRIPT_LOCATION" ]; do - SCRIPT_LOCATION=`"$READLINK" -e "$SCRIPT_LOCATION"` - done -fi - -IDE_HOME=`dirname "$SCRIPT_LOCATION"`/.. -IDE_BIN_HOME=`dirname "$SCRIPT_LOCATION"` - # --------------------------------------------------------------------- # Collect JVM options and properties. # --------------------------------------------------------------------- diff --git a/build/scripts/layouts.gant b/build/scripts/layouts.gant index 84e00419997a..3877aedede7d 100644 --- a/build/scripts/layouts.gant +++ b/build/scripts/layouts.gant @@ -476,10 +476,11 @@ public def layoutCommunityPlugins(String home) { //layout of groovy jars must be consistent with GroovyBuilder.getGroovyRtRoot method jar("groovy-jps-plugin.jar") { module("groovy-jps-plugin") - module("groovy-rt-constants") } jar("groovy_rt.jar") { module("groovy_rt") + } + jar("groovy-rt-constants.jar") { module("groovy-rt-constants") } dir("standardDsls") { diff --git a/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java b/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java index 965452b70408..ce8c831a75f3 100644 --- a/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java +++ b/java/debugger/openapi/src/com/intellij/debugger/SourcePosition.java @@ -32,6 +32,7 @@ import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.lang.ref.WeakReference; import java.util.List; /** @@ -59,7 +60,7 @@ public abstract class SourcePosition implements Navigatable{ @NotNull private final PsiFile myFile; private long myModificationStamp = -1L; - private PsiElement myPsiElement; + private WeakReference myPsiElementRef; private Integer myLine; private Integer myOffset; @@ -120,7 +121,7 @@ public abstract class SourcePosition implements Navigatable{ myModificationStamp = myFile.getModificationStamp(); myLine = null; myOffset = null; - myPsiElement = null; + myPsiElementRef = null; } } @@ -128,7 +129,7 @@ public abstract class SourcePosition implements Navigatable{ if (myModificationStamp != myFile.getModificationStamp()) { return true; } - final PsiElement psiElement = myPsiElement; + final PsiElement psiElement = myPsiElementRef != null ? myPsiElementRef.get() : null; return psiElement != null && !ApplicationManager.getApplication().runReadAction(new Computable() { @Override public Boolean compute() { @@ -158,10 +159,13 @@ public abstract class SourcePosition implements Navigatable{ @Override public PsiElement getElementAt() { updateData(); - if (myPsiElement == null) { - myPsiElement = calcPsiElement(); + PsiElement element = myPsiElementRef != null ? myPsiElementRef.get() : null; + if (element == null) { + element = calcPsiElement(); + myPsiElementRef = new WeakReference(element); + return element; } - return myPsiElement; + return element; } protected int calcLine() { diff --git a/java/execution/impl/src/com/intellij/execution/util/JavaParametersUtil.java b/java/execution/impl/src/com/intellij/execution/util/JavaParametersUtil.java index bec77294cebb..eede2edda506 100644 --- a/java/execution/impl/src/com/intellij/execution/util/JavaParametersUtil.java +++ b/java/execution/impl/src/com/intellij/execution/util/JavaParametersUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 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. @@ -27,6 +27,7 @@ import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleUtilCore; import com.intellij.openapi.project.Project; import com.intellij.openapi.projectRoots.JavaSdk; +import com.intellij.openapi.projectRoots.JdkUtil; import com.intellij.openapi.projectRoots.ProjectJdkTable; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.projectRoots.ex.PathUtilEx; @@ -39,7 +40,6 @@ import org.intellij.lang.annotations.MagicConstant; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.io.File; import java.util.List; import java.util.Map; @@ -90,7 +90,9 @@ public class JavaParametersUtil { } final List entriesForFile = fileIndex.getOrderEntriesForFile(virtualFile); for (OrderEntry entry : entriesForFile) { - if (entry instanceof ExportableOrderEntry && ((ExportableOrderEntry)entry).getScope() == DependencyScope.TEST) return JavaParameters.JDK_AND_CLASSES_AND_TESTS; + if (entry instanceof ExportableOrderEntry && ((ExportableOrderEntry)entry).getScope() == DependencyScope.TEST) { + return JavaParameters.JDK_AND_CLASSES_AND_TESTS; + } } return JavaParameters.JDK_AND_CLASSES; } @@ -106,12 +108,17 @@ public class JavaParametersUtil { configureModule(module, parameters, classPathType, jreHome); } - public static void configureModule(Module module, JavaParameters parameters, @MagicConstant(valuesFromClass = JavaParameters.class) int classPathType, @Nullable String jreHome) throws CantRunException { + public static void configureModule(Module module, + JavaParameters parameters, + @MagicConstant(valuesFromClass = JavaParameters.class) int classPathType, + @Nullable String jreHome) throws CantRunException { parameters.configureByModule(module, classPathType, createModuleJdk(module, jreHome)); } - public static void configureProject(Project project, final JavaParameters parameters, @MagicConstant(valuesFromClass = JavaParameters.class) final int classPathType, @Nullable String jreHome) - throws CantRunException { + public static void configureProject(Project project, + final JavaParameters parameters, + @MagicConstant(valuesFromClass = JavaParameters.class) final int classPathType, + @Nullable String jreHome) throws CantRunException { parameters.configureByProject(project, classPathType, createProjectJdk(project, jreHome)); } @@ -136,23 +143,29 @@ public class JavaParametersUtil { if (configuredJdk != null) { return configuredJdk; } - final boolean isJdk = JavaSdk.checkForJdk(new File(jreHome)); - if (isJdk) { - throw new CantRunException("Alternative JRE path needs to point to a JRE, not to a complete JDK installation"); + + if (JdkUtil.checkForJdk(jreHome)) { + throw new CantRunException(ExecutionBundle.message("jre.path.is.jdk.error.message")); } + if (!JdkUtil.checkForJre(jreHome)) { + throw new CantRunException(ExecutionBundle.message("jre.path.is.not.valid.jre.home.error.message", jreHome)); + } + final Sdk jdk = JavaSdk.getInstance().createJdk("", jreHome); if (jdk == null) throw CantRunException.noJdkConfigured(); return jdk; } - public static void checkAlternativeJRE(CommonJavaRunConfigurationParameters configuration) throws RuntimeConfigurationWarning { + public static void checkAlternativeJRE(@NotNull CommonJavaRunConfigurationParameters configuration) throws RuntimeConfigurationWarning { if (configuration.isAlternativeJrePathEnabled()) { - String alternativeJrePath = configuration.getAlternativeJrePath(); - if (StringUtil.isEmpty(alternativeJrePath) || - ProjectJdkTable.getInstance().findJdk(alternativeJrePath) == null && !JavaSdk.checkForJre(alternativeJrePath)) { - throw new RuntimeConfigurationWarning( - ExecutionBundle.message("jre.path.is.not.valid.jre.home.error.mesage", alternativeJrePath)); - } + checkAlternativeJRE(configuration.getAlternativeJrePath()); + } + } + + public static void checkAlternativeJRE(@Nullable String jrePath) throws RuntimeConfigurationWarning { + if (StringUtil.isEmpty(jrePath) || + ProjectJdkTable.getInstance().findJdk(jrePath) == null && !JavaSdk.checkForJre(jrePath)) { + throw new RuntimeConfigurationWarning(ExecutionBundle.message("jre.path.is.not.valid.jre.home.error.message", jrePath)); } } } diff --git a/java/idea-ui/src/com/intellij/ide/actions/ImportModuleAction.java b/java/idea-ui/src/com/intellij/ide/actions/ImportModuleAction.java index 76e356780b83..c992d544a4e3 100644 --- a/java/idea-ui/src/com/intellij/ide/actions/ImportModuleAction.java +++ b/java/idea-ui/src/com/intellij/ide/actions/ImportModuleAction.java @@ -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. @@ -45,6 +45,8 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import static com.intellij.util.ArrayUtil.toObjectArray; + /** * @author Dmitry Avdeev * Date: 10/31/12 @@ -55,21 +57,31 @@ public class ImportModuleAction extends AnAction { @Override public void actionPerformed(AnActionEvent e) { - final Project project = getEventProject(e); - doImport(project); + doImport(getEventProject(e)); } - public static List doImport(Project project) { + @Override + public void update(AnActionEvent e) { + Presentation presentation = e.getPresentation(); + presentation.setEnabled(getEventProject(e) != null); + } + + @Override + public boolean isDumbAware() { + return true; + } + + public static List doImport(@Nullable Project project) { AddModuleWizard wizard = selectFileAndCreateWizard(project, null); - if (wizard == null) { + + if (wizard == null || wizard.getStepCount() > 0 && !wizard.showAndGet()) { return Collections.emptyList(); } - if (wizard.getStepCount() > 0 && !wizard.showAndGet()) return Collections.emptyList(); return createFromWizard(project, wizard); } - public static List createFromWizard(Project project, AbstractProjectWizard wizard) { + public static List createFromWizard(@Nullable Project project, AbstractProjectWizard wizard) { if (project == null && wizard.getStepCount() > 0) { Project newProject = NewProjectUtil.createFromWizard(wizard, null); return newProject == null ? Collections.emptyList() : Arrays.asList(ModuleManager.getInstance(newProject).getModules()); @@ -82,6 +94,7 @@ public class ImportModuleAction extends AnAction { return Collections.singletonList(module); } else { + assert project != null; return projectBuilder.commit(project); } } @@ -93,23 +106,21 @@ public class ImportModuleAction extends AnAction { } @Nullable - public static AddModuleWizard selectFileAndCreateWizard(final Project project, Component dialogParent) { + public static AddModuleWizard selectFileAndCreateWizard(@Nullable Project project, @Nullable Component dialogParent) { FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleLocalFileDescriptor(); descriptor.setHideIgnored(false); descriptor.setTitle("Select File or Directory to Import"); - ProjectImportProvider[] providers = ProjectImportProvider.PROJECT_IMPORT_PROVIDER.getExtensions(); - String description = getFileChooserDescription(project); + List providers = getProviders(project); + String description = getFileChooserDescription(providers); descriptor.setDescription(description); - - return selectFileAndCreateWizard(project, dialogParent, descriptor, providers); + return selectFileAndCreateWizard(project, dialogParent, descriptor, toObjectArray(providers, ProjectImportProvider.class)); } @Nullable - public static AddModuleWizard selectFileAndCreateWizard(final Project project, + public static AddModuleWizard selectFileAndCreateWizard(@Nullable Project project, @Nullable Component dialogParent, @NotNull FileChooserDescriptor descriptor, - ProjectImportProvider[] providers) - { + ProjectImportProvider[] providers) { FileChooserDialog chooser = FileChooserFactory.getInstance().createFileChooser(descriptor, project, dialogParent); VirtualFile toSelect = null; String lastLocation = PropertiesComponent.getInstance().getValue(LAST_IMPORTED_LOCATION); @@ -126,18 +137,17 @@ public class ImportModuleAction extends AnAction { return createImportWizard(project, dialogParent, file, providers); } - public static String getFileChooserDescription(final Project project) { - ProjectImportProvider[] providers = ProjectImportProvider.PROJECT_IMPORT_PROVIDER.getExtensions(); - List list = ContainerUtil.filter(providers, new Condition() { - @Override - public boolean value(ProjectImportProvider provider) { - return project != null || provider.canCreateNewProject(); - } - }); + /** @deprecated to be removed in IDEA 16 */ + @SuppressWarnings("unused") + public static String getFileChooserDescription(@Nullable final Project project) { + return getFileChooserDescription(getProviders(project)); + } + + private static String getFileChooserDescription(List providers) { StringBuilder builder = new StringBuilder("Select "); boolean first = true; - if (list.size() > 0) { - for (ProjectImportProvider provider : list) { + if (providers.size() > 0) { + for (ProjectImportProvider provider : providers) { String sample = provider.getFileSample(); if (sample != null) { if (!first) { @@ -154,8 +164,19 @@ public class ImportModuleAction extends AnAction { return builder.toString(); } + @NotNull + public static List getProviders(@Nullable final Project project) { + ProjectImportProvider[] providers = ProjectImportProvider.PROJECT_IMPORT_PROVIDER.getExtensions(); + return ContainerUtil.filter(providers, new Condition() { + @Override + public boolean value(ProjectImportProvider provider) { + return project == null ? provider.canCreateNewProject() : provider.canImportModule(); + } + }); + } + @Nullable - public static AddModuleWizard createImportWizard(final Project project, + public static AddModuleWizard createImportWizard(@Nullable final Project project, @Nullable Component dialogParent, final VirtualFile file, ProjectImportProvider... providers) { @@ -180,18 +201,8 @@ public class ImportModuleAction extends AnAction { ProjectImportProvider[] availableProviders = available.toArray(new ProjectImportProvider[available.size()]); - return dialogParent == null ? new AddModuleWizard(project, path, availableProviders) : new AddModuleWizard(project, dialogParent, path, availableProviders); - } - - - @Override - public void update(AnActionEvent e) { - Presentation presentation = e.getPresentation(); - presentation.setEnabled(getEventProject(e) != null); - } - - @Override - public boolean isDumbAware() { - return true; + return dialogParent == null + ? new AddModuleWizard(project, path, availableProviders) + : new AddModuleWizard(project, dialogParent, path, availableProviders); } } diff --git a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/BuildElementsEditor.java b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/BuildElementsEditor.java index a36acc61113c..ba7706c6ad20 100644 --- a/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/BuildElementsEditor.java +++ b/java/idea-ui/src/com/intellij/openapi/roots/ui/configuration/BuildElementsEditor.java @@ -83,14 +83,14 @@ public class BuildElementsEditor extends ModuleElementsEditor { myOutputPathPanel = createOutputPathPanel(ProjectBundle.message("module.paths.output.title"), new CommitPathRunnable() { @Override public void saveUrl(String url) { - if (getCompilerExtension().isCompilerOutputPathInherited()) return; //do not override settings if any + if (myInheritCompilerOutput.isSelected()) return; //do not override settings if any getCompilerExtension().setCompilerOutputPath(url); } }); myTestsOutputPathPanel = createOutputPathPanel(ProjectBundle.message("module.paths.test.output.title"), new CommitPathRunnable() { @Override public void saveUrl(String url) { - if (getCompilerExtension().isCompilerOutputPathInherited()) return; //do not override settings if any + if (myInheritCompilerOutput.isSelected()) return; //do not override settings if any getCompilerExtension().setCompilerOutputPathForTests(url); } }); @@ -218,6 +218,14 @@ public class BuildElementsEditor extends ModuleElementsEditor { } }; + final ActionListener listener = new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + commitRunnable.run(); + } + }; + myPerModuleCompilerOutput.addActionListener(listener); + textField.getDocument().addDocumentListener(new DocumentAdapter() { @Override protected void textChanged(DocumentEvent e) { diff --git a/java/idea-ui/src/com/intellij/projectImport/ProjectImportProvider.java b/java/idea-ui/src/com/intellij/projectImport/ProjectImportProvider.java index 8f79e2b39bc8..cf9319d1428e 100644 --- a/java/idea-ui/src/com/intellij/projectImport/ProjectImportProvider.java +++ b/java/idea-ui/src/com/intellij/projectImport/ProjectImportProvider.java @@ -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. @@ -86,6 +86,10 @@ public abstract class ProjectImportProvider { return true; } + public boolean canImportModule() { + return true; + } + public void addSteps(StepSequence sequence, WizardContext context, String id) { ModuleWizardStep[] steps = createSteps(context); for (ModuleWizardStep step : steps) { diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java index f3f35619dffa..92e639e2543f 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightMethodUtil.java @@ -1040,6 +1040,7 @@ public class HighlightMethodUtil { boolean isInterface = aClass != null && aClass.isInterface(); boolean isExtension = method.hasModifierProperty(PsiModifier.DEFAULT); boolean isStatic = method.hasModifierProperty(PsiModifier.STATIC); + boolean isPrivate = method.hasModifierProperty(PsiModifier.PRIVATE); final List additionalFixes = new ArrayList(); String description = null; @@ -1053,7 +1054,7 @@ public class HighlightMethodUtil { } } else if (isInterface) { - if (!isExtension && !isStatic) { + if (!isExtension && !isStatic && !isPrivate) { description = JavaErrorMessages.message("interface.methods.cannot.have.body"); if (languageLevel.isAtLeast(LanguageLevel.JDK_1_8)) { additionalFixes.add(QUICK_FIX_FACTORY.createModifierListFix(method, PsiModifier.DEFAULT, true, false)); diff --git a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java index ce564b32a415..8f68c7ff4db9 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightUtil.java @@ -154,12 +154,16 @@ public class HighlightUtil extends HighlightUtilBase { Set incompatibles = incompatibleModifiersHash.get(modifier); if (incompatibles == null) return null; final boolean level8OrHigher = PsiUtil.isLanguageLevel8OrHigher(modifierList); + final boolean level9OrHigher = PsiUtil.isLanguageLevel9OrHigher(modifierList); for (@PsiModifier.ModifierConstant String incompatible : incompatibles) { if (level8OrHigher) { if (modifier.equals(PsiModifier.STATIC) && incompatible.equals(PsiModifier.ABSTRACT)){ continue; } } + if (level9OrHigher && modifier.equals(PsiModifier.PRIVATE) && incompatible.equals(PsiModifier.PUBLIC)) { + continue; + } if (modifier.equals(PsiModifier.STATIC) && incompatible.equals(PsiModifier.FINAL)) { final PsiElement parent = modifierList.getParent(); if (parent instanceof PsiMethod) { @@ -475,6 +479,7 @@ public class HighlightUtil extends HighlightUtilBase { HighlightInfo highlightInfo = checkAssignability(lType, rType, initializer, new TextRange(start, end), 0); if (highlightInfo != null) { registerChangeVariableTypeFixes(variable, rType, variable.getInitializer(), highlightInfo); + registerChangeVariableTypeFixes(initializer, lType, null, highlightInfo); } return highlightInfo; } @@ -883,7 +888,8 @@ public class HighlightUtil extends HighlightUtilBase { if (PsiModifier.PRIVATE.equals(modifier) || PsiModifier.PROTECTED.equals(modifier) || PsiModifier.TRANSIENT.equals(modifier) || PsiModifier.STRICTFP.equals(modifier) || PsiModifier.SYNCHRONIZED.equals(modifier)) { - isAllowed &= modifierOwnerParent instanceof PsiClass && !((PsiClass)modifierOwnerParent).isInterface(); + isAllowed &= modifierOwnerParent instanceof PsiClass && + (!((PsiClass)modifierOwnerParent).isInterface() || PsiUtil.isLanguageLevel9OrHigher(modifierOwner)); } if (containingClass != null && containingClass.isAnnotationType()) { @@ -2726,11 +2732,6 @@ public class HighlightUtil extends HighlightUtilBase { QuickFixAction.registerQuickFixAction(highlightInfo, PriorityActionWrapper .lowPriority(method, QUICK_FIX_FACTORY.createMethodReturnFix(method, parameter.getType(), true))); } - } else if (expr instanceof PsiReferenceExpression) { - final PsiElement resolve = ((PsiReferenceExpression)expr).resolve(); - if (resolve instanceof PsiVariable) { - registerChangeVariableTypeFixes((PsiVariable)resolve, parameter.getType(), null, highlightInfo); - } } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java index 5d314a88b103..aa7868f43b4c 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/AnonymousCanBeLambdaInspection.java @@ -36,10 +36,7 @@ import com.intellij.psi.controlFlow.ControlFlowUtil; import com.intellij.psi.impl.source.resolve.DefaultParameterTypeInferencePolicy; import com.intellij.psi.impl.source.resolve.graphInference.FunctionalInterfaceParameterizationUtil; import com.intellij.psi.infos.MethodCandidateInfo; -import com.intellij.psi.util.InheritanceUtil; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.util.PsiTypesUtil; -import com.intellij.psi.util.PsiUtil; +import com.intellij.psi.util.*; import com.intellij.util.ArrayUtilRt; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; @@ -459,14 +456,15 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection private final PsiMethod myMethod; private final PsiAnonymousClass myAnonymClass; - private final boolean myEqualInference; + private final PsiType myInferredType; public ForbiddenRefsChecker(PsiMethod method, PsiAnonymousClass aClass) { myMethod = method; myAnonymClass = aClass; final PsiType inferredType = FunctionalInterfaceParameterizationUtil.getGroundTargetType(getInferredType(aClass)); - myEqualInference = !aClass.getBaseClassType().equals(inferredType); + final PsiClassType baseClassType = aClass.getBaseClassType(); + myInferredType = !baseClassType.equals(inferredType) ? inferredType : null; } @Override @@ -557,14 +555,31 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection } } - if (myEqualInference) { + if (myInferredType != null) { final PsiElement resolved = expression.resolve(); if (resolved instanceof PsiParameter && ((PsiParameter)resolved).getDeclarationScope() == myMethod) { + if (!(myInferredType instanceof PsiClassType)) { + myBodyContainsForbiddenRefs = true; + return; + } final int parameterIndex = myMethod.getParameterList().getParameterIndex((PsiParameter)resolved); for (PsiMethod superMethod : myMethod.findDeepestSuperMethods()) { - if (PsiUtil.resolveClassInType(superMethod.getParameterList().getParameters()[parameterIndex].getType()) instanceof PsiTypeParameter) { - myBodyContainsForbiddenRefs = true; - return; + final PsiType paramType = superMethod.getParameterList().getParameters()[parameterIndex].getType(); + final PsiClass superClass = superMethod.getContainingClass(); + if (superClass != null) { + final PsiClassType.ClassResolveResult classResolveResult = ((PsiClassType)myInferredType).resolveGenerics(); + final PsiClass classCandidate = classResolveResult.getElement(); + if (classCandidate == null) { + myBodyContainsForbiddenRefs = true; + return; + } + final PsiSubstitutor inferredSubstitutor = TypeConversionUtil.getClassSubstitutor(superClass, classCandidate, classResolveResult.getSubstitutor()); + final PsiSubstitutor substitutor = TypeConversionUtil.getSuperClassSubstitutor(superClass, myAnonymClass.getBaseClassType()); + if (inferredSubstitutor == null || + !Comparing.equal(inferredSubstitutor.substitute(paramType), substitutor.substitute(paramType))) { + myBodyContainsForbiddenRefs = true; + return; + } } } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/ExplicitTypeCanBeDiamondInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/ExplicitTypeCanBeDiamondInspection.java index b39171e76b89..100cc979e235 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/ExplicitTypeCanBeDiamondInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/ExplicitTypeCanBeDiamondInspection.java @@ -22,8 +22,9 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.TextRange; import com.intellij.psi.*; +import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.impl.PsiDiamondTypeUtil; -import com.intellij.psi.impl.source.tree.ChildRole; +import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.Nls; import org.jetbrains.annotations.NotNull; @@ -97,7 +98,11 @@ public class ExplicitTypeCanBeDiamondInspection extends BaseJavaBatchLocalInspec public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { final PsiElement element = descriptor.getPsiElement(); if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return; - PsiDiamondTypeUtil.replaceExplicitWithDiamond(element); + final PsiNewExpression newExpression = + PsiTreeUtil.getParentOfType(PsiDiamondTypeUtil.replaceExplicitWithDiamond(element), PsiNewExpression.class); + if (newExpression != null) { + CodeStyleManager.getInstance(project).reformat(newExpression); + } } } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java index 3403ed5584d9..d2ddea29e9ef 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspectionBase.java @@ -141,7 +141,8 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool { PsiClass containingClass = PsiTreeUtil.getParentOfType(scope, PsiClass.class); if (containingClass != null && PsiUtil.isLocalOrAnonymousClass(containingClass)) return; - final StandardDataFlowRunner dfaRunner = new StandardDataFlowRunner(TREAT_UNKNOWN_MEMBERS_AS_NULLABLE, true) { + final StandardDataFlowRunner dfaRunner = new StandardDataFlowRunner(TREAT_UNKNOWN_MEMBERS_AS_NULLABLE, !isInsideConstructorOrInitializer( + scope)) { @Override protected boolean shouldCheckTimeLimit() { if (!onTheFly) return false; @@ -151,6 +152,15 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool { analyzeDfaWithNestedClosures(scope, holder, dfaRunner, Arrays.asList(dfaRunner.createMemoryState()), onTheFly); } + private static boolean isInsideConstructorOrInitializer(PsiElement element) { + while (element != null) { + element = PsiTreeUtil.getParentOfType(element, PsiMethod.class, PsiClassInitializer.class); + if (element instanceof PsiClassInitializer) return true; + if (element instanceof PsiMethod && ((PsiMethod)element).isConstructor()) return true; + } + return false; + } + private void analyzeDfaWithNestedClosures(PsiElement scope, ProblemsHolder holder, StandardDataFlowRunner dfaRunner, @@ -190,7 +200,7 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool { final PsiElementFactory elementFactory = JavaPsiFacade.getInstance(project).getElementFactory(); final PsiBinaryExpression binary = (PsiBinaryExpression)elementFactory.createExpressionFromText("a != null", null); binary.getLOperand().replace(qualifier); - ContainerUtil.addIfNotNull(fixes, createAssertFix(binary)); + ContainerUtil.addIfNotNull(fixes, createAssertFix(binary, expression)); } addSurroundWithIfFix(qualifier, fixes, onTheFly); @@ -206,7 +216,7 @@ public class DataFlowInspectionBase extends BaseJavaBatchLocalInspectionTool { } } - protected LocalQuickFix createAssertFix(PsiBinaryExpression binary) { + protected LocalQuickFix createAssertFix(PsiBinaryExpression binary, PsiExpression expression) { return null; } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaPsiUtil.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaPsiUtil.java index 6d223ef16bd4..090d1389c8d1 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaPsiUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/DfaPsiUtil.java @@ -20,6 +20,7 @@ import com.intellij.codeInspection.dataFlow.instructions.Instruction; import com.intellij.codeInspection.dataFlow.instructions.MethodCallInstruction; import com.intellij.codeInspection.dataFlow.instructions.ReturnInstruction; import com.intellij.codeInspection.dataFlow.value.DfaValueFactory; +import com.intellij.lang.java.JavaLanguage; import com.intellij.openapi.util.Ref; import com.intellij.psi.*; import com.intellij.psi.search.LocalSearchScope; @@ -113,8 +114,11 @@ public class DfaPsiUtil { } private static Set getNotNullInitializedFields(final PsiMethod constructor, final PsiClass containingClass) { + if (!constructor.getLanguage().isKindOf(JavaLanguage.INSTANCE)) return Collections.emptySet(); + final PsiCodeBlock body = constructor.getBody(); if (body == null) return Collections.emptySet(); + return CachedValuesManager.getCachedValue(constructor, new CachedValueProvider>() { @Nullable @Override @@ -200,6 +204,7 @@ public class DfaPsiUtil { private static MultiMap getAllConstructorFieldInitializers(final PsiClass psiClass) { if (psiClass instanceof PsiCompiledElement) { + //noinspection unchecked return MultiMap.EMPTY; } @@ -231,7 +236,9 @@ public class DfaPsiUtil { }; for (PsiMethod constructor : psiClass.getConstructors()) { - constructor.accept(visitor); + if (constructor.getLanguage().isKindOf(JavaLanguage.INSTANCE)) { + constructor.accept(visitor); + } } return Result.create(result, psiClass); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaInheritorsGetter.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaInheritorsGetter.java index a503de4d93a5..e96eb36c6385 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaInheritorsGetter.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaInheritorsGetter.java @@ -156,7 +156,7 @@ public class JavaInheritorsGetter extends CompletionProvider= 2 && statement == siblings[siblings.length - 2] && lastOne instanceof PsiExpressionStatement) { + int start = statement.getTextRange().getStartOffset(); + int end = lastOne.getTextRange().getStartOffset(); + return !StringUtil.contains(statement.getContainingFile().getViewProvider().getContents(), start, end, '\n'); + } + + return false; } } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java b/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java index bb9d86e7fb32..d62907af849e 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java @@ -48,6 +48,7 @@ import java.util.*; */ public class JavaCompletionProcessor extends BaseScopeProcessor implements ElementClassHint { + private final boolean myInJavaDoc; private boolean myStatic = false; private PsiElement myDeclarationHolder = null; private final Set myResultNames = new THashSet(new TObjectHashingStrategy() { @@ -87,7 +88,8 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme myMatcher = nameCondition; myFilter = filter; PsiElement scope = element; - if (JavaResolveUtil.isInJavaDoc(myElement)) myMembersFlag = true; + myInJavaDoc = JavaResolveUtil.isInJavaDoc(myElement); + if (myInJavaDoc) myMembersFlag = true; while(scope != null && !(scope instanceof PsiFile) && !(scope instanceof PsiClass)){ scope = scope.getContext(); } @@ -308,13 +310,16 @@ public class JavaCompletionProcessor extends BaseScopeProcessor implements Eleme } public boolean isAccessible(@Nullable final PsiElement element) { - if (!myOptions.checkAccess) return true; + if (!myOptions.checkAccess && myInJavaDoc) return true; if (!(element instanceof PsiMember)) return true; PsiMember member = (PsiMember)element; PsiClass accessObjectClass = myQualified ? myQualifierClass : null; - return JavaPsiFacade.getInstance(element.getProject()).getResolveHelper().isAccessible(member, member.getModifierList(), myElement, - accessObjectClass, myDeclarationHolder); + if (JavaPsiFacade.getInstance(element.getProject()).getResolveHelper().isAccessible(member, member.getModifierList(), myElement, + accessObjectClass, myDeclarationHolder)) { + return true; + } + return !myOptions.checkAccess && !(element instanceof PsiCompiledElement); } public void setCompletionElements(@NotNull Object[] elements) { diff --git a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingMethodBodyFixer.java b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingMethodBodyFixer.java index ae5c0423b7ff..ee01b1b82dde 100644 --- a/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingMethodBodyFixer.java +++ b/java/java-impl/src/com/intellij/codeInsight/editorActions/smartEnter/MissingMethodBodyFixer.java @@ -67,8 +67,9 @@ public class MissingMethodBodyFixer implements Fixer { static boolean shouldHaveBody(PsiMethod method) { PsiClass containingClass = method.getContainingClass(); if (containingClass == null) return false; - if (containingClass.isInterface() && !method.hasModifierProperty(DEFAULT)) return false; - if (method.hasModifierProperty(ABSTRACT)) return false; - return !method.hasModifierProperty(NATIVE); + if (method.hasModifierProperty(PRIVATE)) return true; + if (method.hasModifierProperty(ABSTRACT) || method.hasModifierProperty(NATIVE)) return false; + if (containingClass.isInterface() && !method.hasModifierProperty(DEFAULT) && !method.hasModifierProperty(STATIC)) return false; + return true; } } diff --git a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java index d7ec7920d09b..de132b85be40 100644 --- a/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/dataFlow/DataFlowInspection.java @@ -26,6 +26,7 @@ import com.intellij.psi.PsiAssignmentExpression; import com.intellij.psi.PsiBinaryExpression; import com.intellij.psi.PsiExpression; import com.intellij.psi.tree.IElementType; +import com.intellij.refactoring.util.RefactoringUtil; import javax.swing.*; import javax.swing.event.ChangeEvent; @@ -59,8 +60,8 @@ public class DataFlowInspection extends DataFlowInspectionBase { } @Override - protected AddAssertStatementFix createAssertFix(PsiBinaryExpression binary) { - return new AddAssertStatementFix(binary); + protected AddAssertStatementFix createAssertFix(PsiBinaryExpression binary, PsiExpression expression) { + return RefactoringUtil.getParentStatement(expression, false) == null ? null : new AddAssertStatementFix(binary); } private class OptionsPanel extends JPanel { diff --git a/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java b/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java index cb215d06380d..1f4ea60f0278 100644 --- a/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java +++ b/java/java-impl/src/com/intellij/lang/java/JavaDocumentationProvider.java @@ -762,7 +762,7 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext @Override public boolean hasDocumentationFor(PsiElement element, PsiElement originalElement) { - return CompositeDocumentationProvider.hasUrlsFor(this, element, originalElement); + return CompositeDocumentationProvider.hasBrowsableUrlsFor(this, element, originalElement); } @Override diff --git a/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/IntroduceParameterObjectProcessor.java b/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/IntroduceParameterObjectProcessor.java index 54335f2363f9..7d73c576455f 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/IntroduceParameterObjectProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/IntroduceParameterObjectProcessor.java @@ -211,13 +211,15 @@ public class IntroduceParameterObjectProcessor extends FixableUsagesRefactoringP final ParameterChunk parameterChunk = ParameterChunk.getChunkByParameter(parameter, parameters); @NonNls String getter = parameterChunk != null ? parameterChunk.getter : null; + final String paramName = parameterChunk != null ? parameterChunk.parameter.name : replacedParameter.getName(); + final PsiType paramType = parameterChunk != null ? parameterChunk.parameter.type : replacedParameter.getType(); if (getter == null) { - getter = GenerateMembersUtil.suggestGetterName(replacedParameter.getName(), replacedParameter.getType(), myProject); + getter = GenerateMembersUtil.suggestGetterName(paramName, paramType, myProject); paramsNeedingGetters.add(replacedParameter); } @NonNls String setter = parameterChunk != null ? parameterChunk.setter : null; if (setter == null) { - setter = GenerateMembersUtil.suggestSetterName(replacedParameter.getName(), replacedParameter.getType(), myProject); + setter = GenerateMembersUtil.suggestSetterName(paramName, paramType, myProject); } if (RefactoringUtil.isPlusPlusOrMinusMinus(paramUsage.getParent())) { usages.add(new ReplaceParameterIncrementDecrement(paramUsage, fixedParamName, setter, getter)); diff --git a/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/usageInfo/MergeMethodArguments.java b/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/usageInfo/MergeMethodArguments.java index f127efd9f450..0aecd58be007 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/usageInfo/MergeMethodArguments.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceparameterobject/usageInfo/MergeMethodArguments.java @@ -16,6 +16,8 @@ package com.intellij.refactoring.introduceparameterobject.usageInfo; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; @@ -66,14 +68,15 @@ public class MergeMethodArguments extends FixableUsageInfo { } public void fixUsage() throws IncorrectOperationException { - final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(method.getProject()); + final Project project = method.getProject(); + final JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(project); final PsiMethod deepestSuperMethod = method.findDeepestSuperMethod(); final PsiClass psiClass; if (myContainingClass != null) { psiClass = myContainingClass.findInnerClassByName(className, false); } else { - psiClass = psiFacade.findClass(StringUtil.getQualifiedName(packageName, className), GlobalSearchScope.allScope(getProject())); + psiClass = psiFacade.findClass(StringUtil.getQualifiedName(packageName, className), GlobalSearchScope.allScope(project)); } assert psiClass != null; PsiSubstitutor subst = PsiSubstitutor.EMPTY; @@ -93,12 +96,12 @@ public class MergeMethodArguments extends FixableUsageInfo { } } final List parametersInfo = new ArrayList(); - final PsiClassType classType = JavaPsiFacade.getElementFactory(getProject()).createType(psiClass, subst); + final PsiClassType classType = JavaPsiFacade.getElementFactory(project).createType(psiClass, subst); final ParameterInfoImpl mergedParamInfo = new ParameterInfoImpl(-1, parameterName, classType, null) { @Override public PsiExpression getValue(final PsiCallExpression expr) throws IncorrectOperationException { - return (PsiExpression)JavaCodeStyleManager.getInstance(getProject()) + return (PsiExpression)JavaCodeStyleManager.getInstance(project) .shortenClassReferences(psiFacade.getElementFactory().createExpressionFromText(getMergedParam(expr), expr)); } }; @@ -114,9 +117,9 @@ public class MergeMethodArguments extends FixableUsageInfo { } parametersInfo.add(firstIncludedIdx == -1 ? 0 : firstIncludedIdx, mergedParamInfo); - final SmartPsiElementPointer meth = SmartPointerManager.getInstance(getProject()).createSmartPsiElementPointer(method); + final SmartPsiElementPointer meth = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(method); - Runnable performChangeSignatureRunnable = new Runnable() { + final Runnable performChangeSignatureRunnable = new Runnable() { @Override public void run() { final PsiMethod psiMethod = meth.getElement(); @@ -134,7 +137,12 @@ public class MergeMethodArguments extends FixableUsageInfo { if (ApplicationManager.getApplication().isUnitTestMode()) { performChangeSignatureRunnable.run(); } else { - ApplicationManager.getApplication().invokeLater(performChangeSignatureRunnable); + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + CommandProcessor.getInstance().runUndoTransparentAction(performChangeSignatureRunnable); + } + }); } } diff --git a/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeMethodStaticProcessor.java b/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeMethodStaticProcessor.java index ec8c635d496e..0f31060bd355 100644 --- a/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeMethodStaticProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/makeStatic/MakeMethodStaticProcessor.java @@ -83,7 +83,7 @@ public class MakeMethodStaticProcessor extends MakeMethodOrClassStaticProcessor< @Override protected MultiMap getConflictDescriptions(UsageInfo[] usages) { MultiMap descriptions = super.getConflictDescriptions(usages); - if (mySettings.isMakeClassParameter()) { + if (mySettings.isMakeClassParameter() || mySettings.isMakeFieldParameters()) { for (UsageInfo usage : usages) { PsiElement element = usage.getElement(); if (element instanceof PsiMethodReferenceExpression) { @@ -329,7 +329,7 @@ public class MakeMethodStaticProcessor extends MakeMethodOrClassStaticProcessor< if (anchor != null) { anchor = argList.addAfter(fieldRef, anchor); } - else { + else if (argList != null) { if (exprs.length > 0) { anchor = argList.addBefore(fieldRef, exprs[0]); } diff --git a/java/java-psi-api/src/com/intellij/psi/PsiClassType.java b/java/java-psi-api/src/com/intellij/psi/PsiClassType.java index 4d3ff916f5fe..1d4e1f36716b 100644 --- a/java/java-psi-api/src/com/intellij/psi/PsiClassType.java +++ b/java/java-psi-api/src/com/intellij/psi/PsiClassType.java @@ -82,7 +82,11 @@ public abstract class PsiClassType extends PsiType { public boolean equals(Object obj) { if (this == obj) return true; - if (!(obj instanceof PsiClassType)) return false; + if (!(obj instanceof PsiClassType)) { + return obj instanceof PsiCapturedWildcardType && + ((PsiCapturedWildcardType)obj).getLowerBound().equalsToText(CommonClassNames.JAVA_LANG_OBJECT) && + equalsToText(CommonClassNames.JAVA_LANG_OBJECT); + } PsiClassType otherClassType = (PsiClassType)obj; String className = getClassName(); diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java index b31aa352c1f9..1d1978d0948e 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java @@ -889,6 +889,10 @@ public final class PsiUtil extends PsiUtilCore { return getLanguageLevel(element).isAtLeast(LanguageLevel.JDK_1_8); } + public static boolean isLanguageLevel9OrHigher(@NotNull final PsiElement element) { + return getLanguageLevel(element).isAtLeast(LanguageLevel.JDK_1_9); + } + @NotNull public static LanguageLevel getLanguageLevel(@NotNull PsiElement element) { if (element instanceof PsiDirectory) { diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java index 925c0ee46543..125b4f6942fa 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/PsiModifierListImpl.java @@ -130,7 +130,10 @@ public class PsiModifierListImpl extends JavaStubPsiElement return false; } if (type == JavaTokenType.ABSTRACT_KEYWORD) { - return getNode().findChildByType(JavaTokenType.DEFAULT_KEYWORD) == null && getNode().findChildByType(JavaTokenType.STATIC_KEYWORD) == null; + final ASTNode node = getNode(); + return node.findChildByType(JavaTokenType.DEFAULT_KEYWORD) == null && + node.findChildByType(JavaTokenType.STATIC_KEYWORD) == null && + node.findChildByType(JavaTokenType.PRIVATE_KEYWORD) == null; } } } diff --git a/java/java-tests/testData/actions/reformatFileInEditor/formatSelection_DoNotTouchTrailingWhiteSpaces_after.java b/java/java-tests/testData/actions/reformatFileInEditor/formatSelection_DoNotTouchTrailingWhiteSpaces_after.java new file mode 100644 index 000000000000..3dfde165f400 --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/formatSelection_DoNotTouchTrailingWhiteSpaces_after.java @@ -0,0 +1,10 @@ +public class T { + + + public void tutu() { + + } + + + public void test() {} +} \ No newline at end of file diff --git a/java/java-tests/testData/actions/reformatFileInEditor/formatSelection_DoNotTouchTrailingWhiteSpaces_before.java b/java/java-tests/testData/actions/reformatFileInEditor/formatSelection_DoNotTouchTrailingWhiteSpaces_before.java new file mode 100644 index 000000000000..c8d45129804d --- /dev/null +++ b/java/java-tests/testData/actions/reformatFileInEditor/formatSelection_DoNotTouchTrailingWhiteSpaces_before.java @@ -0,0 +1,10 @@ +public class T { + + + public void tutu() { + + } + + + public void test() {} +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completeStatement/PrivateInterfaceMethodBody.java b/java/java-tests/testData/codeInsight/completeStatement/PrivateInterfaceMethodBody.java new file mode 100644 index 000000000000..7135e23aab5a --- /dev/null +++ b/java/java-tests/testData/codeInsight/completeStatement/PrivateInterfaceMethodBody.java @@ -0,0 +1,3 @@ +public interface Foo { + private void foo() +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completeStatement/PrivateInterfaceMethodBody_after.java b/java/java-tests/testData/codeInsight/completeStatement/PrivateInterfaceMethodBody_after.java new file mode 100644 index 000000000000..19bf06276f44 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completeStatement/PrivateInterfaceMethodBody_after.java @@ -0,0 +1,5 @@ +public interface Foo { + private void foo() { + + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completeStatement/StaticInterfaceMethodBody.java b/java/java-tests/testData/codeInsight/completeStatement/StaticInterfaceMethodBody.java new file mode 100644 index 000000000000..f63c25feca47 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completeStatement/StaticInterfaceMethodBody.java @@ -0,0 +1,3 @@ +public interface Foo { + static void foo() +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completeStatement/StaticInterfaceMethodBody_after.java b/java/java-tests/testData/codeInsight/completeStatement/StaticInterfaceMethodBody_after.java new file mode 100644 index 000000000000..88c8a706208c --- /dev/null +++ b/java/java-tests/testData/codeInsight/completeStatement/StaticInterfaceMethodBody_after.java @@ -0,0 +1,5 @@ +public interface Foo { + static void foo() { + + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/normal/NoInaccessibleCompiledElements.java b/java/java-tests/testData/codeInsight/completion/normal/NoInaccessibleCompiledElements.java new file mode 100644 index 000000000000..48fe7eaf319a --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normal/NoInaccessibleCompiledElements.java @@ -0,0 +1,7 @@ +public class Foo { + + void foo() { + registerNat + } + +} diff --git a/java/java-tests/testData/codeInsight/completion/normalSorting/PreferReturnBeforeExpression.java b/java/java-tests/testData/codeInsight/completion/normalSorting/PreferReturnBeforeExpression.java new file mode 100644 index 000000000000..c07f96c0a0f2 --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/normalSorting/PreferReturnBeforeExpression.java @@ -0,0 +1,10 @@ +public class Test { + + int rMethod() {} + + int foo(int rParam) { + Object rLocal; + r rMethod(); + } + +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting9/PrivateInInterfaces.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting9/PrivateInInterfaces.java new file mode 100644 index 000000000000..280cb8a6cab3 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting9/PrivateInInterfaces.java @@ -0,0 +1,3 @@ +interface A { + private void m() {} +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/SuperObjectCapturedWildcardEquality.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/SuperObjectCapturedWildcardEquality.java new file mode 100644 index 000000000000..0edb93cf37bd --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/genericsHighlighting/SuperObjectCapturedWildcardEquality.java @@ -0,0 +1,9 @@ +class A {} + +class Test { + { + A queue = null; + A q = queue; + queue = q; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addAssert/beforeFieldInitializer.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addAssert/beforeFieldInitializer.java new file mode 100644 index 000000000000..43349e1119df --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/addAssert/beforeFieldInitializer.java @@ -0,0 +1,5 @@ +// "Assert 'myFoo != null'" "false" +class A{ + private final String myFoo = null; + String myBar = myFoo.substring(0); +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterParamCouldBeInferred.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterParamCouldBeInferred.java new file mode 100644 index 000000000000..2779c21701af --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/afterParamCouldBeInferred.java @@ -0,0 +1,19 @@ +// "Replace with lambda" "true" + +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +class Test { + private static final Map WORD_TO_MOOD = null; + + public static void analyseMood(String[] wordsInMessage) { + Stream.of(wordsInMessage) + .map(s -> WORD_TO_MOOD.get(s)) + .filter(mood -> mood != null) + .collect(Collectors.toSet()); + } + + enum Mood {} +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeParamCouldBeInferred.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeParamCouldBeInferred.java new file mode 100644 index 000000000000..ef91d0d27daf --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/anonymous2lambda/beforeParamCouldBeInferred.java @@ -0,0 +1,24 @@ +// "Replace with lambda" "true" + +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +class Test { + private static final Map WORD_TO_MOOD = null; + + public static void analyseMood(String[] wordsInMessage) { + Stream.of(wordsInMessage) + .map(new Function() { + @Override + public Mood apply(String s) { + return WORD_TO_MOOD.get(s); + } + }) + .filter(mood -> mood != null) + .collect(Collectors.toSet()); + } + + enum Mood {} +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/afterReformatArgs.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/afterReformatArgs.java new file mode 100644 index 000000000000..4afd888ea0ce --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/afterReformatArgs.java @@ -0,0 +1,8 @@ +// "Replace with <>" "true" +class Test { + public Test(String s1, String s2) {} + + Test s = new Test<>("s1", + "s2"); + +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/beforeReformatArgs.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/beforeReformatArgs.java new file mode 100644 index 000000000000..9546b5a47a9f --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/explicit2diamond/beforeReformatArgs.java @@ -0,0 +1,8 @@ +// "Replace with <>" "true" +class Test { + public Test(String s1, String s2) {} + + Test s = new Testing>("s1", + "s2"); + +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/afterVararg.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/afterVararg.java new file mode 100644 index 000000000000..d3f05c041881 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/afterVararg.java @@ -0,0 +1,8 @@ +// "Change field 'foo' type to 'java.lang.String[]'" "true" + +class Base { + private String[] foo; + public void bar(String... args) { + foo = args; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/beforeVararg.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/beforeVararg.java new file mode 100644 index 000000000000..acdd4b75e4c2 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/variableType/beforeVararg.java @@ -0,0 +1,8 @@ +// "Change field 'foo' type to 'java.lang.String[]'" "true" + +class Base { + private String foo; + public void bar(String... args) { + foo = args; + } +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/dataFlow/fixture/FinalFieldInConstructorAnonymous.java b/java/java-tests/testData/inspection/dataFlow/fixture/FinalFieldInConstructorAnonymous.java new file mode 100644 index 000000000000..3ae7943d010b --- /dev/null +++ b/java/java-tests/testData/inspection/dataFlow/fixture/FinalFieldInConstructorAnonymous.java @@ -0,0 +1,26 @@ +class SomeClass { + private final Object myField; + + { + if (myField != null) { // false-positive report 'condition is always true' + System.out.println(myField.toString()); + } + } + + public SomeClass(SomeOtherClass o) { + o.invoke(new Runnable() { + public void run() { + if (myField != null) { // false-positive report 'condition is always true' + System.out.println(myField.toString()); + } + } + }); + myField = "xxx"; + } +} + +class SomeOtherClass { + public void invoke(Runnable r) { + r.run(); + } +} diff --git a/java/java-tests/testData/refactoring/makeMethodStatic/afterThisMethodReference.java b/java/java-tests/testData/refactoring/makeMethodStatic/afterThisMethodReference.java new file mode 100644 index 000000000000..787f64715b88 --- /dev/null +++ b/java/java-tests/testData/refactoring/makeMethodStatic/afterThisMethodReference.java @@ -0,0 +1,10 @@ +class Test4 { + void test() { + Runnable f = Test4::yyy; + } + + String myField = ""; + static void yyy() { + System.out.println(myField); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/makeMethodStatic/beforeThisMethodReference.java b/java/java-tests/testData/refactoring/makeMethodStatic/beforeThisMethodReference.java new file mode 100644 index 000000000000..68bb88337754 --- /dev/null +++ b/java/java-tests/testData/refactoring/makeMethodStatic/beforeThisMethodReference.java @@ -0,0 +1,10 @@ +class Test4 { + void test() { + Runnable f = this::yyy; + } + + String myField = ""; + void yyy() { + System.out.println(myField); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java index 430af5b03de9..ac52cab1714a 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/CompleteStatementTest.java @@ -18,7 +18,6 @@ package com.intellij.codeInsight; import com.intellij.JavaTestUtil; import com.intellij.lang.java.JavaLanguage; import com.intellij.openapi.actionSystem.IdeActions; -import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.testFramework.EditorActionTestCase; @@ -272,6 +271,8 @@ public class CompleteStatementTest extends EditorActionTestCase { public void testGenericMethodBody() throws Exception { doTest(); } public void testDefaultMethodBody() { doTest(); } + public void testStaticInterfaceMethodBody() { doTest(); } + public void testPrivateInterfaceMethodBody() { doTest(); } public void testArrayInitializerRBracket() throws Exception { doTest(); } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionInEditorTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionInEditorTest.java index 058d165c3ddf..578ba79bad81 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionInEditorTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/actions/ReformatCodeActionInEditorTest.java @@ -102,4 +102,9 @@ public class ReformatCodeActionInEditorTest extends LightPlatformCodeInsightFixt public void testFormatOptimizeRearrangeVcsChanges() { doTest(new ReformatCodeRunOptions(VCS_CHANGED_TEXT).setOptimizeImports(true).setRearrangeCode(true)); } + + public void testFormatSelection_DoNotTouchTrailingWhiteSpaces() { + //todo actually test is not working, and working test is not working + doTest(new ReformatCodeRunOptions(SELECTED_TEXT)); + } } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy index 821e5f31fb91..e0bc158b921b 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionOrderingTest.groovy @@ -110,7 +110,7 @@ public class NormalCompletionOrderingTest extends CompletionSortingTestCase { final String path = getTestName(false) + ".java"; myFixture.configureByFile(path); myFixture.complete(CompletionType.BASIC, 2); - assertPreferredItems(0, "BOOLEAN", "booleanMethod", "AN_OBJECT", "voidMethod", "registerNatives"); + assertPreferredItems(0, "BOOLEAN", "booleanMethod", "AN_OBJECT", "voidMethod"); } public void testDispreferDeclared() throws Throwable { @@ -288,6 +288,10 @@ public class NormalCompletionOrderingTest extends CompletionSortingTestCase { checkPreferredItems(0, "return", "rLocal", "rParam", "rMethod"); } + public void testPreferReturnBeforeExpression() { + checkPreferredItems(0, "return", "rLocal", "rParam", "rMethod"); + } + public void testPreferModifiers() { checkPreferredItems(0, "private", "protected", "public", "paaa", "paab"); } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy index 35a96080dc02..5f5870b2d34c 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy +++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy @@ -1493,6 +1493,14 @@ class Bar { myFixture.assertPreferredCompletionItems(0, "xcreateZoo", "xcreateElephant"); } + public void testNoInaccessibleCompiledElements() { + configure() + myFixture.complete(CompletionType.BASIC, 2) + checkResultByFile(getTestName(false) + ".java"); + assertEmpty(myItems); + assertNull(getLookup()); + } + public void "test code cleanup during completion generation"() { myFixture.configureByText "a.java", "class Foo {int i; ge}" myFixture.enableInspections(new UnqualifiedFieldAccessInspection()) diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java index 718518b93ec4..4b8f1b6a4701 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/GenericsHighlightingTest.java @@ -471,6 +471,10 @@ public class GenericsHighlightingTest extends LightDaemonAnalyzerTestCase { doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); } + public void testSuperObjectCapturedWildcardEquality() throws Exception { + doTest(LanguageLevel.JDK_1_7, JavaSdkVersion.JDK_1_7, false); + } + public void testJavaUtilCollections_NoVerify() throws Exception { PsiClass collectionsClass = getJavaFacade().findClass("java.util.Collections", GlobalSearchScope.moduleWithLibrariesScope(getModule())); assertNotNull(collectionsClass); diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk9Test.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk9Test.java index d36a4580c143..0c4874791fec 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk9Test.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/LightAdvHighlightingJdk9Test.java @@ -53,4 +53,5 @@ public class LightAdvHighlightingJdk9Test extends LightDaemonAnalyzerTestCase { } public void testSafeVarargsApplicability() { doTest(true, false); } + public void testPrivateInInterfaces() { doTest(false, false); } } diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Simplify2DiamondInspectionsTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Simplify2DiamondInspectionsTest.java index 44dcc2e1780b..ac74905ef4c9 100644 --- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Simplify2DiamondInspectionsTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/quickFix/Simplify2DiamondInspectionsTest.java @@ -17,12 +17,17 @@ package com.intellij.codeInsight.daemon.quickFix; import com.intellij.codeInspection.ExplicitTypeCanBeDiamondInspection; import com.intellij.codeInspection.LocalInspectionTool; +import com.intellij.lang.java.JavaLanguage; import com.intellij.pom.java.LanguageLevel; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CodeStyleSettingsManager; +import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import org.jetbrains.annotations.NotNull; //todo test3 should be checked if it compiles - as now javac infers Object instead of String?! public class Simplify2DiamondInspectionsTest extends LightQuickFixParameterizedTestCase { + @NotNull @Override protected LocalInspectionTool[] configureLocalInspectionTools() { @@ -31,6 +36,26 @@ public class Simplify2DiamondInspectionsTest extends LightQuickFixParameterizedT }; } + private boolean myAlignment; + + @Override + protected void setUp() throws Exception { + super.setUp(); + CommonCodeStyleSettings settings = getSettings(); + myAlignment = settings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS; + settings.ALIGN_MULTILINE_PARAMETERS_IN_CALLS = true; + } + + @Override + protected void tearDown() throws Exception { + getSettings().ALIGN_MULTILINE_PARAMETERS_IN_CALLS = myAlignment; + super.tearDown(); + } + + private CommonCodeStyleSettings getSettings() { + return CodeStyleSettingsManager.getSettings(getProject()).getCommonSettings(JavaLanguage.INSTANCE); + } + public void test() throws Exception { doAllTests(); } @Override diff --git a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java index c65376379e40..16f34a8d7449 100644 --- a/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java +++ b/java/java-tests/testSrc/com/intellij/codeInspection/DataFlowInspectionTest.java @@ -194,6 +194,7 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase { public void testRememberLocalTransientFieldState() { doTest(); } public void testFinalFieldDuringInitialization() { doTest(); } public void testFinalFieldDuringSuperInitialization() { doTest(); } + public void testFinalFieldInConstructorAnonymous() { doTest(); } public void _testSymmetricUncheckedCast() { doTest(); } // https://youtrack.jetbrains.com/issue/IDEABKL-6871 public void testNullCheckDoesntAffectUncheckedCast() { doTest(); } public void testThrowNull() { doTest(); } diff --git a/java/java-tests/testSrc/com/intellij/refactoring/MakeMethodStaticTest.java b/java/java-tests/testSrc/com/intellij/refactoring/MakeMethodStaticTest.java index 6427e2e05265..ad12405f4265 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/MakeMethodStaticTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/MakeMethodStaticTest.java @@ -203,6 +203,10 @@ public class MakeMethodStaticTest extends LightRefactoringTestCase { doTest(true); } + public void testThisMethodReference() throws Exception { + doTest(false); + } + public void testPreserveParametersAlignment() throws Exception { doTest(); } diff --git a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java index 467b18f1778c..9640351c40cc 100644 --- a/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java +++ b/java/structuralsearch-java/src/com/intellij/structuralsearch/impl/matcher/JavaMatchingVisitor.java @@ -1471,26 +1471,47 @@ public class JavaMatchingVisitor extends JavaElementVisitor { @Override public void visitNewExpression(final PsiNewExpression new1) { - if (myMatchingVisitor.getElement() instanceof PsiArrayInitializerExpression && - myMatchingVisitor.getElement().getParent() instanceof PsiVariable && + final PsiElement other = myMatchingVisitor.getElement(); + final PsiJavaCodeReferenceElement classReference = new1.getClassReference(); + if (other instanceof PsiArrayInitializerExpression && + other.getParent() instanceof PsiVariable && new1.getArrayDimensions().length == 0 && new1.getArrayInitializer() != null ) { - myMatchingVisitor.setResult( - myMatchingVisitor.match(new1.getClassReference(), ((PsiVariable)myMatchingVisitor.getElement().getParent()).getTypeElement())); - myMatchingVisitor.matchSons(new1.getArrayInitializer(), myMatchingVisitor.getElement()); + final boolean looseMatching = myMatchingVisitor.getMatchContext().getOptions().isLooseMatching(); + final boolean typedVar = myMatchingVisitor.getMatchContext().getPattern().isTypedVar(classReference); + if ((typedVar || !looseMatching) && !allowsAbsenceOfMatch(classReference)) { + myMatchingVisitor.setResult(false); + return; + } + final PsiElementFactory factory = JavaPsiFacade.getElementFactory(other.getProject()); + final PsiType otherType = ((PsiVariable)other.getParent()).getType(); + final PsiTypeElement otherTypeElement = factory.createTypeElement(otherType.getDeepComponentType()); + final MatchContext matchContext = myMatchingVisitor.getMatchContext(); + final MatchingHandler handler = matchContext.getPattern().getHandler(classReference); + if (handler instanceof SubstitutionHandler) { + final SubstitutionHandler substitutionHandler = (SubstitutionHandler)handler; + myMatchingVisitor.setResult(substitutionHandler.handle(otherTypeElement, matchContext)); + } + else { + final PsiType type = new1.getType(); + myMatchingVisitor.setResult(type != null && type.equals(otherType)); + } + if (myMatchingVisitor.getResult()) { + myMatchingVisitor.matchSons(new1.getArrayInitializer(), other); + } return; } - if (!(myMatchingVisitor.getElement() instanceof PsiNewExpression)) { + if (!(other instanceof PsiNewExpression)) { myMatchingVisitor.setResult(false); return; } - final PsiNewExpression new2 = (PsiNewExpression)myMatchingVisitor.getElement(); + final PsiNewExpression new2 = (PsiNewExpression)other; - if (new1.getClassReference() != null) { + if (classReference != null) { if (new2.getClassReference() != null) { - myMatchingVisitor.setResult(myMatchingVisitor.match(new1.getClassReference(), new2.getClassReference()) && + myMatchingVisitor.setResult(myMatchingVisitor.match(classReference, new2.getClassReference()) && myMatchingVisitor.matchSons(new1.getArrayInitializer(), new2.getArrayInitializer())); if (myMatchingVisitor.getResult()) { @@ -1507,7 +1528,7 @@ public class JavaMatchingVisitor extends JavaElementVisitor { if (element != null && element.getNextSibling() instanceof PsiKeyword) { ((LexicalNodesFilter)LexicalNodesFilter.getInstance()).setCareKeyWords(true); - myMatchingVisitor.setResult(myMatchingVisitor.match(new1.getClassReference(), element.getNextSibling()) && + myMatchingVisitor.setResult(myMatchingVisitor.match(classReference, element.getNextSibling()) && myMatchingVisitor.matchSons(new1.getArrayInitializer(), new2.getArrayInitializer())); ((LexicalNodesFilter)LexicalNodesFilter.getInstance()).setCareKeyWords(false); @@ -1521,17 +1542,17 @@ public class JavaMatchingVisitor extends JavaElementVisitor { } } - if (new1.getClassReference() == new2.getClassReference()) { + if (classReference == new2.getClassReference()) { // probably anonymous class or array of primitive type ((LexicalNodesFilter)LexicalNodesFilter.getInstance()).setCareKeyWords(true); myMatchingVisitor.setResult(myMatchingVisitor.matchSons(new1, new2)); ((LexicalNodesFilter)LexicalNodesFilter.getInstance()).setCareKeyWords(false); } else if (new1.getAnonymousClass() == null && - new1.getClassReference() != null && + classReference != null && new2.getAnonymousClass() != null) { // allow matching anonymous class without pattern - myMatchingVisitor.setResult(myMatchingVisitor.match(new1.getClassReference(), new2.getAnonymousClass().getBaseClassReference()) && + myMatchingVisitor.setResult(myMatchingVisitor.match(classReference, new2.getAnonymousClass().getBaseClassReference()) && myMatchingVisitor.matchSons(new1.getArgumentList(), new2.getArgumentList())); } else { diff --git a/java/testFramework/src/com/intellij/testFramework/fixtures/impl/JavaModuleFixtureBuilderImpl.java b/java/testFramework/src/com/intellij/testFramework/fixtures/impl/JavaModuleFixtureBuilderImpl.java index 9eed50d2f46b..c196b832dec2 100644 --- a/java/testFramework/src/com/intellij/testFramework/fixtures/impl/JavaModuleFixtureBuilderImpl.java +++ b/java/testFramework/src/com/intellij/testFramework/fixtures/impl/JavaModuleFixtureBuilderImpl.java @@ -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 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"); } diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java index 95116641dcec..1aab89c35f11 100644 --- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java +++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/BuildSession.java @@ -33,6 +33,7 @@ import org.jetbrains.jps.builders.*; import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType; import org.jetbrains.jps.builders.java.dependencyView.Callbacks; import org.jetbrains.jps.incremental.MessageHandler; +import org.jetbrains.jps.incremental.RebuildRequestedException; import org.jetbrains.jps.incremental.TargetTypeRegistry; import org.jetbrains.jps.incremental.Utils; import org.jetbrains.jps.incremental.fs.BuildFSState; @@ -567,14 +568,13 @@ final class BuildSession implements Runnable, CanceledStatus { return event.getChangedPathsCount() != 0 || event.getDeletedPathsCount() != 0; } - private void finishBuild(Throwable error, boolean hadBuildErrors, boolean doneSomething) { + private void finishBuild(final Throwable error, boolean hadBuildErrors, boolean doneSomething) { CmdlineRemoteProto.Message lastMessage = null; try { if (error instanceof CannotLoadJpsModelException) { String text = "Failed to load project configuration: " + StringUtil.decapitalize(error.getMessage()); String path = ((CannotLoadJpsModelException)error).getFile().getAbsolutePath(); - lastMessage = CmdlineProtoUtil.toMessage(mySessionId, CmdlineProtoUtil.createCompileMessage(BuildMessage.Kind.ERROR, text, path, - -1, -1, -1, -1, -1, -1.0f)); + lastMessage = CmdlineProtoUtil.toMessage(mySessionId, CmdlineProtoUtil.createCompileMessage(BuildMessage.Kind.ERROR, text, path, -1, -1, -1, -1, -1, -1.0f)); } else if (error != null) { Throwable cause = error.getCause(); @@ -596,6 +596,9 @@ final class BuildSession implements Runnable, CanceledStatus { if (!trace.isEmpty()) { messageText.append("\n").append(trace); } + if (error instanceof RebuildRequestedException) { + messageText.append("\n").append("Please perform full project rebuild (Build | Rebuild Project)"); + } lastMessage = CmdlineProtoUtil.toMessage(mySessionId, CmdlineProtoUtil.createFailure(messageText.toString(), cause)); } else { diff --git a/platform/core-api/src/com/intellij/openapi/application/ModalityInvokator.java b/platform/core-api/src/com/intellij/openapi/application/ModalityInvokator.java index 4a72e09dcd8e..579f64c4a587 100644 --- a/platform/core-api/src/com/intellij/openapi/application/ModalityInvokator.java +++ b/platform/core-api/src/com/intellij/openapi/application/ModalityInvokator.java @@ -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. @@ -13,16 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -/* - * @author max - */ package com.intellij.openapi.application; import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.Condition; import org.jetbrains.annotations.NotNull; +/** + * @author max + */ public interface ModalityInvokator { /** * Causes runnable.run() to be executed asynchronously on the diff --git a/platform/core-api/src/com/intellij/openapi/vfs/DeprecatedVirtualFileSystem.java b/platform/core-api/src/com/intellij/openapi/vfs/DeprecatedVirtualFileSystem.java index 680facb3290c..47cf71739717 100644 --- a/platform/core-api/src/com/intellij/openapi/vfs/DeprecatedVirtualFileSystem.java +++ b/platform/core-api/src/com/intellij/openapi/vfs/DeprecatedVirtualFileSystem.java @@ -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 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"); + } } \ No newline at end of file diff --git a/platform/core-api/src/com/intellij/testFramework/LightVirtualFileBase.java b/platform/core-api/src/com/intellij/testFramework/LightVirtualFileBase.java index edf10bd92491..5e91c468c985 100644 --- a/platform/core-api/src/com/intellij/testFramework/LightVirtualFileBase.java +++ b/platform/core-api/src/com/intellij/testFramework/LightVirtualFileBase.java @@ -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(); diff --git a/platform/core-api/src/com/intellij/util/IconUtil.java b/platform/core-api/src/com/intellij/util/IconUtil.java index 84919411598a..77831aa864a6 100644 --- a/platform/core-api/src/com/intellij/util/IconUtil.java +++ b/platform/core-api/src/com/intellij/util/IconUtil.java @@ -425,9 +425,8 @@ public class IconUtil { final BufferedImage img = UIUtil.createImage(source.getIconWidth(), source.getIconHeight(), Transparency.TRANSLUCENT); int[] rgba = new int[4]; float[] hsb = new float[3]; - boolean hiDPI = RetinaImage.isAppleHiDPIScaledImage(image); - for (int y = 0; y < image.getHeight() * (hiDPI ? 2 : 1); y++) { - for (int x = 0; x < image.getWidth() * (hiDPI ? 2 : 1); x++) { + for (int y = 0; y < image.getRaster().getHeight(); y++) { + for (int x = 0; x < image.getRaster().getWidth(); x++) { image.getRaster().getPixel(x, y, rgba); if (rgba[3] != 0) { Color.RGBtoHSB(rgba[0], rgba[1], rgba[2], hsb); diff --git a/platform/core-impl/src/com/intellij/openapi/vfs/impl/jar/CoreJarFileSystem.java b/platform/core-impl/src/com/intellij/openapi/vfs/impl/jar/CoreJarFileSystem.java index b1fb350126aa..a106c2a0f277 100644 --- a/platform/core-impl/src/com/intellij/openapi/vfs/impl/jar/CoreJarFileSystem.java +++ b/platform/core-impl/src/com/intellij/openapi/vfs/impl/jar/CoreJarFileSystem.java @@ -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"); - } } diff --git a/platform/core-impl/src/com/intellij/openapi/vfs/local/CoreLocalFileSystem.java b/platform/core-impl/src/com/intellij/openapi/vfs/local/CoreLocalFileSystem.java index b9d99c404486..39a54934b6fa 100644 --- a/platform/core-impl/src/com/intellij/openapi/vfs/local/CoreLocalFileSystem.java +++ b/platform/core-impl/src/com/intellij/openapi/vfs/local/CoreLocalFileSystem.java @@ -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; - } } diff --git a/platform/lang-api/src/com/intellij/execution/configurations/RunConfigurationBase.java b/platform/lang-api/src/com/intellij/execution/configurations/RunConfigurationBase.java index 020395f3005f..bc364075a823 100644 --- a/platform/lang-api/src/com/intellij/execution/configurations/RunConfigurationBase.java +++ b/platform/lang-api/src/com/intellij/execution/configurations/RunConfigurationBase.java @@ -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. @@ -22,12 +22,14 @@ import com.intellij.execution.runners.ProgramRunner; import com.intellij.openapi.options.SettingsEditor; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.InvalidDataException; +import com.intellij.openapi.util.JDOMExternalizerUtil; import com.intellij.openapi.util.UserDataHolderBase; import com.intellij.openapi.util.WriteExternalException; +import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters; +import com.intellij.util.xmlb.XmlSerializer; import com.intellij.util.xmlb.annotations.Attribute; import com.intellij.util.xmlb.annotations.Transient; import org.jdom.Element; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -40,24 +42,22 @@ import java.util.List; * * @author dyoma */ -public abstract class RunConfigurationBase extends UserDataHolderBase - implements RunConfiguration, TargetAwareRunProfile { +public abstract class RunConfigurationBase extends UserDataHolderBase implements RunConfiguration, TargetAwareRunProfile { + private static final String LOG_FILE = "log_file"; + private static final String PREDEFINED_LOG_FILE_ELEMENT = "predefined_log_file"; + private static final String FILE_OUTPUT = "output_file"; + private static final String SAVE = "is_save"; + private static final String OUTPUT_FILE = "path"; + private static final String SHOW_CONSOLE_ON_STD_OUT = "show_console_on_std_out"; + private static final String SHOW_CONSOLE_ON_STD_ERR = "show_console_on_std_err"; + private final ConfigurationFactory myFactory; private final Project myProject; private String myName = ""; + private final Icon myIcon; private ArrayList myLogFiles = new ArrayList(); private ArrayList myPredefinedLogFiles = new ArrayList(); - - @NonNls private static final String LOG_FILE = "log_file"; - @NonNls private static final String PREDEFINED_LOG_FILE_ELEMENT = "predefined_log_file"; - @NonNls private static final String FILE_OUTPUT = "output_file"; - @NonNls private static final String SAVE = "is_save"; - @NonNls private static final String OUTPUT_FILE = "path"; - @NonNls private static final String SHOW_CONSOLE_ON_STD_OUT = "show_console_on_std_out"; - @NonNls private static final String SHOW_CONSOLE_ON_STD_ERR = "show_console_on_std_err"; - - private final Icon myIcon; private boolean mySaveOutput = false; private boolean myShowConsoleOnStdOut = false; private boolean myShowConsoleOnStdErr = false; @@ -111,7 +111,8 @@ public abstract class RunConfigurationBase extends UserDataHolderBase return super.hashCode(); } - public void checkRunnerSettings(@NotNull ProgramRunner runner, @Nullable RunnerSettings runnerSettings, + public void checkRunnerSettings(@NotNull ProgramRunner runner, + @Nullable RunnerSettings runnerSettings, @Nullable ConfigurationPerRunnerSettings configurationPerRunnerSettings) throws RuntimeConfigurationException { } @@ -223,22 +224,17 @@ public abstract class RunConfigurationBase extends UserDataHolderBase @Override public void writeExternal(Element element) throws WriteExternalException { - for (final LogFileOptions options : myLogFiles) { - Element logFile = new Element(LOG_FILE); - options.writeExternal(logFile); - element.addContent(logFile); - } - for (PredefinedLogFile predefinedLogFile : myPredefinedLogFiles) { - Element fileElement = new Element(PREDEFINED_LOG_FILE_ELEMENT); - predefinedLogFile.writeExternal(fileElement); - element.addContent(fileElement); - } - final Element fileOutputPathElement = new Element(FILE_OUTPUT); - if (myFileOutputPath != null) { - fileOutputPathElement.setAttribute(OUTPUT_FILE, myFileOutputPath); - } - fileOutputPathElement.setAttribute(SAVE, String.valueOf(mySaveOutput)); + JDOMExternalizerUtil.addChildren(element, LOG_FILE, myLogFiles); + JDOMExternalizerUtil.addChildren(element, PREDEFINED_LOG_FILE_ELEMENT, myPredefinedLogFiles); + if (myFileOutputPath != null || mySaveOutput) { + Element fileOutputPathElement = new Element(FILE_OUTPUT); + if (myFileOutputPath != null) { + fileOutputPathElement.setAttribute(OUTPUT_FILE, myFileOutputPath); + } + if (mySaveOutput) { + fileOutputPathElement.setAttribute(SAVE, String.valueOf(mySaveOutput)); + } element.addContent(fileOutputPathElement); } diff --git a/platform/lang-api/src/com/intellij/lang/documentation/CompositeDocumentationProvider.java b/platform/lang-api/src/com/intellij/lang/documentation/CompositeDocumentationProvider.java index 14a7c4b99a94..69862071749f 100644 --- a/platform/lang-api/src/com/intellij/lang/documentation/CompositeDocumentationProvider.java +++ b/platform/lang-api/src/com/intellij/lang/documentation/CompositeDocumentationProvider.java @@ -16,6 +16,7 @@ package com.intellij.lang.documentation; +import com.intellij.ide.BrowserUtil; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.project.Project; @@ -190,7 +191,7 @@ public class CompositeDocumentationProvider extends DocumentationProviderEx impl if (((ExternalDocumentationProvider)provider).hasDocumentationFor(element, originalElement)) return true; } else { - if (hasUrlsFor(provider, element, originalElement)) return true; + if (hasBrowsableUrlsFor(provider, element, originalElement)) return true; } } return false; @@ -224,6 +225,12 @@ public class CompositeDocumentationProvider extends DocumentationProviderEx impl return false; } + public static boolean hasBrowsableUrlsFor(DocumentationProvider provider, PsiElement element, PsiElement originalElement) { + final List urls = BrowserUtil.retainBrowsableUrls(provider.getUrlFor(element, originalElement)); + if (urls != null && !urls.isEmpty()) return true; + return false; + } + @Nullable @Override public PsiElement getCustomDocumentationElement(@NotNull Editor editor, diff --git a/platform/lang-api/src/com/intellij/lang/documentation/ExternalDocumentationProvider.java b/platform/lang-api/src/com/intellij/lang/documentation/ExternalDocumentationProvider.java index 3172726f282e..5d8ab6177322 100644 --- a/platform/lang-api/src/com/intellij/lang/documentation/ExternalDocumentationProvider.java +++ b/platform/lang-api/src/com/intellij/lang/documentation/ExternalDocumentationProvider.java @@ -31,8 +31,10 @@ public interface ExternalDocumentationProvider { String fetchExternalDocumentation(final Project project, PsiElement element, final List docUrls); /** - * Quick check for existence of external documentation for specified element. Called from action update, so must be fast. - * If not implemented, update check is performed by calling {@link DocumentationProvider#getUrlFor(com.intellij.psi.PsiElement, com.intellij.psi.PsiElement)}. + * Quick check for existence of external documentation for specified element which can be displayed in external browser. + * Called from action update, so must be fast. If not implemented, update check is performed by calling + * {@link DocumentationProvider#getUrlFor(PsiElement, PsiElement)} and retaining only 'browsable' urls + * (see {@link com.intellij.ide.BrowserUtil#canBeBrowsed(String)}). * * @param element the element to check for existence of documentation * @param originalElement the element at caret (on which the action was invoked) diff --git a/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java b/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java index 6641d531c590..b8d12b2bfa9c 100644 --- a/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java +++ b/platform/lang-api/src/com/intellij/openapi/projectRoots/JdkUtil.java @@ -98,8 +98,12 @@ public class JdkUtil { return null; } + public static boolean checkForJdk(@NotNull String homePath) { + return checkForJdk(new File(FileUtil.toSystemDependentName(homePath))); + } + public static boolean checkForJdk(@NotNull File homePath) { - File binPath = new File(homePath.getAbsolutePath() + File.separator + "bin"); + File binPath = new File(homePath, "bin"); if (!binPath.exists()) return false; FileFilter fileFilter = new FileFilter() { @@ -117,8 +121,11 @@ public class JdkUtil { } public static boolean checkForJre(@NotNull String homePath) { - homePath = new File(FileUtil.toSystemDependentName(homePath)).getAbsolutePath(); - File binPath = new File(homePath + File.separator + "bin"); + return checkForJre(new File(FileUtil.toSystemDependentName(homePath))); + } + + public static boolean checkForJre(@NotNull File homePath) { + File binPath = new File(homePath, "bin"); if (!binPath.exists()) return false; FileFilter fileFilter = new FileFilter() { @@ -130,7 +137,7 @@ public class JdkUtil { File[] children = binPath.listFiles(fileFilter); return children != null && children.length >= 1 && - checkForRuntime(homePath); + checkForRuntime(homePath.getAbsolutePath()); } public static boolean checkForRuntime(@NotNull String homePath) { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java index 0fe2e90f25c7..ae57a1a6b77d 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/FormatChangedTextUtil.java @@ -22,7 +22,6 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.EditorFactory; import com.intellij.openapi.editor.impl.EditorFactoryImpl; -import com.intellij.openapi.editor.markup.RangeHighlighter; import com.intellij.openapi.module.ModifiableModuleModel; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; @@ -38,7 +37,6 @@ import com.intellij.openapi.vcs.ex.LineStatusTracker; import com.intellij.openapi.vcs.ex.Range; import com.intellij.openapi.vcs.ex.RangesBuilder; import com.intellij.openapi.vcs.impl.LineStatusTrackerManager; -import com.intellij.openapi.vcs.impl.LineStatusTrackerManagerI; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiDirectory; import com.intellij.psi.PsiDocumentManager; @@ -51,7 +49,8 @@ import com.intellij.util.diff.FilesTooBigForDiffException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.Collection; +import java.util.List; public class FormatChangedTextUtil { public static final Key TEST_REVISION_CONTENT = Key.create("test.revision.content"); @@ -158,52 +157,6 @@ public class FormatChangedTextUtil { } } - /** - * Allows to ask for the changed text of the given file (in comparison with VCS). - * - * @param file target file - * @return collection of changed regions for the given file - */ - @NotNull - public static Collection getChanges(@NotNull PsiFile file) { - final Set defaultResult = Collections.singleton(file.getTextRange()); - final VirtualFile virtualFile = file.getVirtualFile(); - if (virtualFile != null) { - final Change change = ChangeListManager.getInstance(file.getProject()).getChange(virtualFile); - if (change != null && change.getType() == Change.Type.NEW) { - return defaultResult; - } - } - - final LineStatusTrackerManagerI manager = LineStatusTrackerManager.getInstance(file.getProject()); - if (manager == null) { - return defaultResult; - } - final Document document = PsiDocumentManager.getInstance(file.getProject()).getDocument(file); - if (document == null) { - return defaultResult; - } - final LineStatusTracker lineStatusTracker = manager.getLineStatusTracker(document); - if (lineStatusTracker == null) { - return defaultResult; - } - final List ranges = lineStatusTracker.getRanges(); - if (ranges == null || ranges.isEmpty()) { - return defaultResult; - } - - List result = new ArrayList(); - for (Range range : ranges) { - if (range.getType() != Range.DELETED) { - final RangeHighlighter highlighter = range.getHighlighter(); - if (highlighter != null) { - result.add(new TextRange(highlighter.getStartOffset(), highlighter.getEndOffset())); - } - } - } - return result; - } - @NotNull public static List getChangedFilesFromDirs(@NotNull Project project, @NotNull List dirs) { ChangeListManager changeListManager = ChangeListManager.getInstance(project); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java index e9f80bd23fad..0bfb4cc31238 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/actions/ReformatCodeProcessor.java @@ -54,7 +54,7 @@ public class ReformatCodeProcessor extends AbstractLayoutCodeProcessor { } public ReformatCodeProcessor(@NotNull PsiFile file, @NotNull SelectionModel selectionModel) { - super(file.getProject(), file, COMMAND_NAME, PROGRESS_TEXT, false); + super(file.getProject(), file, PROGRESS_TEXT, COMMAND_NAME, false); mySelectionModel = selectionModel; } diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java index 3cac97504db1..bb22d980c5ed 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationComponent.java @@ -28,6 +28,7 @@ import com.intellij.ide.actions.ExternalJavaDocAction; import com.intellij.lang.documentation.CompositeDocumentationProvider; import com.intellij.lang.documentation.DocumentationProvider; import com.intellij.lang.documentation.ExternalDocumentationHandler; +import com.intellij.lang.documentation.ExternalDocumentationProvider; import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.*; import com.intellij.openapi.actionSystem.impl.ActionButton; @@ -39,7 +40,6 @@ import com.intellij.openapi.editor.ex.EditorSettingsExternalizable; import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.options.FontSize; import com.intellij.openapi.ui.popup.JBPopup; -import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.Disposer; import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.util.text.StringUtil; @@ -55,7 +55,6 @@ import com.intellij.ui.SideBorder; import com.intellij.ui.components.JBLayeredPane; import com.intellij.ui.components.JBScrollPane; import com.intellij.util.Consumer; -import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashMap; import com.intellij.util.ui.GraphicsUtil; import com.intellij.util.ui.UIUtil; @@ -698,13 +697,6 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr } } - private static final Condition BROWSABLE_URL = new Condition() { - @Override - public boolean value(String s) { - return BrowserUtil.canBeBrowsed(s); - } - }; - private class ExternalDocAction extends AnAction implements HintManagerImpl.ActionToIgnore { public ExternalDocAction() { super(CodeInsightBundle.message("javadoc.action.view.external"), null, AllIcons.Actions.Browser_externalJavaDoc); @@ -730,10 +722,10 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr if (!processed) { final Component component = PlatformDataKeys.CONTEXT_COMPONENT.getData(e.getDataContext()); final List urls; - if (!StringUtil.isEmptyOrSpaces(myEffectiveExternalUrl) && BROWSABLE_URL.value(myEffectiveExternalUrl)) { + if (!StringUtil.isEmptyOrSpaces(myEffectiveExternalUrl) && BrowserUtil.canBeBrowsed(myEffectiveExternalUrl)) { urls = Collections.singletonList(myEffectiveExternalUrl); } else { - urls = getBrowsableUrls(provider.getUrlFor(element, originalElement)); + urls = BrowserUtil.retainBrowsableUrls(provider.getUrlFor(element, originalElement)); assert urls != null : provider; assert !urls.isEmpty() : provider; } @@ -750,15 +742,15 @@ public class DocumentationComponent extends JPanel implements Disposable, DataPr final PsiElement element = myElement.getElement(); final DocumentationProvider provider = DocumentationManager.getProviderFromElement(element); final PsiElement originalElement = DocumentationManager.getOriginalElement(element); - List urls = getBrowsableUrls(provider.getUrlFor(element, originalElement)); - presentation.setEnabled(element != null && urls != null && !urls.isEmpty()); + if (provider instanceof ExternalDocumentationProvider) { + presentation.setEnabled(element != null && ((ExternalDocumentationProvider)provider).hasDocumentationFor(element, originalElement)); + } + else { + List urls = BrowserUtil.retainBrowsableUrls(provider.getUrlFor(element, originalElement)); + presentation.setEnabled(element != null && urls != null && !urls.isEmpty()); + } } } - - @Nullable - private List getBrowsableUrls(@Nullable List urls) { - return urls == null ? null : ContainerUtil.filter(urls, BROWSABLE_URL); - } } private void registerActions() { diff --git a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java index a9e6e31fa20d..20c4ce397241 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/documentation/DocumentationManager.java @@ -1080,10 +1080,7 @@ public class DocumentationManager extends DockablePopupManager compute() { final SmartPsiElementPointer originalElementPtr = myElement.getUserData(ORIGINAL_ELEMENT_KEY); final PsiElement originalElement = originalElementPtr != null ? originalElementPtr.getElement() : null; - if (((ExternalDocumentationProvider)provider).hasDocumentationFor(myElement, originalElement)) { - return provider.getUrlFor(myElement, originalElement); - } - return null; + return provider.getUrlFor(myElement, originalElement); } } ); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java b/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java index 29aacc3716cc..c7232ed6d012 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/hint/actions/ShowImplementationsAction.java @@ -148,6 +148,11 @@ public class ShowImplementationsAction extends AnAction implements PopupAction { } } + //check attached sources if any + if (element instanceof PsiCompiledElement) { + element = element.getNavigationElement(); + } + String text = ""; PsiElement[] impls = new PsiElement[0]; if (element != null) { diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java index 66fcefae01f7..ff706074942e 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/DefaultInspectionToolPresentation.java @@ -62,7 +62,7 @@ public class DefaultInspectionToolPresentation implements ProblemDescriptionsPro @NotNull private final GlobalInspectionContextImpl myContext; protected static String ourOutputPath; - protected InspectionNode myToolNode; + private InspectionNode myToolNode; private static final Object lock = new Object(); private final Map myProblemElements = Collections.synchronizedMap(new THashMap()); @@ -77,6 +77,8 @@ public class DefaultInspectionToolPresentation implements ProblemDescriptionsPro protected static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.ex.DescriptorProviderInspection"); private boolean isDisposed; + private final Object myToolLock = new Object(); + public DefaultInspectionToolPresentation(@NotNull InspectionToolWrapper toolWrapper, @NotNull GlobalInspectionContextImpl context) { myToolWrapper = toolWrapper; myContext = context; @@ -226,14 +228,16 @@ public class DefaultInspectionToolPresentation implements ProblemDescriptionsPro return; } final InspectionNode toolNode; - if (myToolNode == null) { - final HighlightSeverity currentSeverity = getSeverity((RefElement)refElement); - toolNode = view.addTool(myToolWrapper, HighlightDisplayLevel.find(currentSeverity), context.getUIOptions().GROUP_BY_SEVERITY); - } - else { - toolNode = myToolNode; - if (toolNode.isTooBigForOnlineRefresh()) { - return; + synchronized (myToolLock) { + if (myToolNode == null) { + final HighlightSeverity currentSeverity = getSeverity((RefElement)refElement); + toolNode = view.addTool(myToolWrapper, HighlightDisplayLevel.find(currentSeverity), context.getUIOptions().GROUP_BY_SEVERITY); + } + else { + toolNode = myToolNode; + if (toolNode.isTooBigForOnlineRefresh()) { + return; + } } } final Map problems = new HashMap(); @@ -262,6 +266,13 @@ public class DefaultInspectionToolPresentation implements ProblemDescriptionsPro } } + + public void setToolNode(InspectionNode toolNode) { + synchronized (myToolLock) { + myToolNode = toolNode; + } + } + protected boolean isDisposed() { return isDisposed; } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java index 85e660401fea..268e48a1b8b1 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ui/InspectionResultsView.java @@ -469,7 +469,7 @@ public class InspectionResultsView extends JPanel implements Disposable, Occuren myProvider.appendToolNodeContent(myGlobalInspectionContext, toolNode, parentNode, showStructure); InspectionToolPresentation presentation = myGlobalInspectionContext.getPresentation(toolWrapper); toolNode = presentation.createToolNode(myGlobalInspectionContext, toolNode, myProvider, parentNode, showStructure); - ((DefaultInspectionToolPresentation)presentation).myToolNode = toolNode; + ((DefaultInspectionToolPresentation)presentation).setToolNode(toolNode); registerActionShortcuts(presentation); return toolNode; diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java index 9eced8b4fc92..0550e75fc05a 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java @@ -100,10 +100,14 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo public static final Key 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); diff --git a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java index cabb8f3f2494..bbca8e8ad8f5 100644 --- a/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java +++ b/platform/lang-impl/src/com/intellij/find/impl/livePreview/LivePreview.java @@ -406,7 +406,7 @@ public class LivePreview extends DocumentAdapter implements SearchResults.Search balloonBuilder.setCloseButtonEnabled(true); myReplacementBalloon = balloonBuilder.createBalloon(); - myReplacementBalloon.show(new ReplacementBalloonPositionTracker(editor), Balloon.Position.above); + myReplacementBalloon.show(new ReplacementBalloonPositionTracker(editor), Balloon.Position.below); } private void hideBalloon() { @@ -534,7 +534,7 @@ public class LivePreview extends DocumentAdapter implements SearchResults.Search Point startPoint = myEditor.visualPositionToXY(myEditor.offsetToVisualPosition(startOffset)); Point endPoint = myEditor.visualPositionToXY(myEditor.offsetToVisualPosition(endOffset)); - Point point = new Point((startPoint.x + endPoint.x)/2, startPoint.y); + Point point = new Point((startPoint.x + endPoint.x)/2, startPoint.y + myEditor.getLineHeight()); return new RelativePoint(myEditor.getContentComponent(), point); } diff --git a/platform/lang-impl/src/com/intellij/ide/actions/ExternalJavaDocAction.java b/platform/lang-impl/src/com/intellij/ide/actions/ExternalJavaDocAction.java index 50525bc0e288..2e3325b5ea2c 100644 --- a/platform/lang-impl/src/com/intellij/ide/actions/ExternalJavaDocAction.java +++ b/platform/lang-impl/src/com/intellij/ide/actions/ExternalJavaDocAction.java @@ -78,7 +78,7 @@ public class ExternalJavaDocAction extends AnAction { return; } - final List urls = provider.getUrlFor(element, originalElement); + final List urls = BrowserUtil.retainBrowsableUrls(provider.getUrlFor(element, originalElement)); if (urls != null && !urls.isEmpty()) { showExternalJavadoc(urls, PlatformDataKeys.CONTEXT_COMPONENT.getData(dataContext)); } @@ -126,7 +126,7 @@ public class ExternalJavaDocAction extends AnAction { enabled = edProvider.hasDocumentationFor(element, originalElement) || edProvider.canPromptToConfigureDocumentation(element); } else { - final List urls = provider.getUrlFor(element, originalElement); + final List urls = BrowserUtil.retainBrowsableUrls(provider.getUrlFor(element, originalElement)); enabled = urls != null && !urls.isEmpty(); } if (editor != null) { diff --git a/platform/lang-impl/src/com/intellij/ide/util/projectWizard/ProjectSettingsStepBase.java b/platform/lang-impl/src/com/intellij/ide/util/projectWizard/ProjectSettingsStepBase.java index 9d3d09b5f24d..f9e8f919ad22 100644 --- a/platform/lang-impl/src/com/intellij/ide/util/projectWizard/ProjectSettingsStepBase.java +++ b/platform/lang-impl/src/com/intellij/ide/util/projectWizard/ProjectSettingsStepBase.java @@ -265,7 +265,7 @@ public class ProjectSettingsStepBase extends AbstractActionWithPanel implements final FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor(); myLocationField.addBrowseFolderListener("Select base directory", "Select base directory for the Project", null, descriptor); - return LabeledComponent.create(myLocationField, "Location"); + return LabeledComponent.create(myLocationField, "&Location"); } private static File findSequentNonExistingUntitled() { diff --git a/platform/lang-impl/src/com/intellij/lang/javascript/boilerplate/GithubProjectGeneratorPeer.java b/platform/lang-impl/src/com/intellij/lang/javascript/boilerplate/GithubProjectGeneratorPeer.java index 7c069b566d13..df78bef783c5 100644 --- a/platform/lang-impl/src/com/intellij/lang/javascript/boilerplate/GithubProjectGeneratorPeer.java +++ b/platform/lang-impl/src/com/intellij/lang/javascript/boilerplate/GithubProjectGeneratorPeer.java @@ -180,7 +180,7 @@ public class GithubProjectGeneratorPeer implements WebProjectGenerator.Generator @Override public void buildUI(@NotNull SettingsStep settingsStep) { - settingsStep.addSettingsField("\u001BVersion:", myVersionPanel); + settingsStep.addSettingsField("&Version:", myVersionPanel); settingsStep.addSettingsComponent(myReloadableComboBoxPanel.getErrorComponent()); } diff --git a/platform/lang-impl/src/com/intellij/openapi/roots/impl/storage/ClasspathStorage.java b/platform/lang-impl/src/com/intellij/openapi/roots/impl/storage/ClasspathStorage.java index 6cacde77e1e6..1a1eef8a246c 100644 --- a/platform/lang-impl/src/com/intellij/openapi/roots/impl/storage/ClasspathStorage.java +++ b/platform/lang-impl/src/com/intellij/openapi/roots/impl/storage/ClasspathStorage.java @@ -115,6 +115,8 @@ public class ClasspathStorage extends StateStorageBase KEY = Key.create("indent.options.notification.provider"); private static final Key NOTIFIED_FLAG = Key.create("indent.options.notification.provider.status"); protected static final Key DETECT_INDENT_NOTIFICATION_SHOWN_KEY = Key.create("indent.options.notification.provider.status.test.notification.shown"); + protected static final Key SHOW_NOTIFICATION_IN_TEST = Key.create("indent.options.notification.provider.should.update.notification.in.test"); @NotNull @Override @@ -106,13 +107,19 @@ public class DetectedIndentOptionsNotificationProvider extends EditorNotificatio } public static void updateIndentNotification(@NotNull PsiFile file, boolean enforce) { - if (!ApplicationManager.getApplication().isHeadlessEnvironment() || ApplicationManager.getApplication().isUnitTestMode()) { - FileEditor fileEditor = FileEditorManager.getInstance(file.getProject()).getSelectedEditor(file.getVirtualFile()); + VirtualFile vFile = file.getVirtualFile(); + if (vFile == null) return; + + if (!ApplicationManager.getApplication().isHeadlessEnvironment() + || ApplicationManager.getApplication().isUnitTestMode() + && vFile.getUserData(SHOW_NOTIFICATION_IN_TEST) != null) + { + FileEditor fileEditor = FileEditorManager.getInstance(file.getProject()).getSelectedEditor(vFile); if (fileEditor != null) { Boolean notifiedFlag = fileEditor.getUserData(NOTIFIED_FLAG); if (notifiedFlag == null || enforce) { fileEditor.putUserData(NOTIFIED_FLAG, Boolean.TRUE); - EditorNotifications.getInstance(file.getProject()).updateNotifications(file.getVirtualFile()); + EditorNotifications.getInstance(file.getProject()).updateNotifications(vFile); } } } diff --git a/platform/lang-impl/src/com/intellij/psi/templateLanguages/TemplateDataElementType.java b/platform/lang-impl/src/com/intellij/psi/templateLanguages/TemplateDataElementType.java index f5b1170ed2de..5c2d6fd7805c 100644 --- a/platform/lang-impl/src/com/intellij/psi/templateLanguages/TemplateDataElementType.java +++ b/platform/lang-impl/src/com/intellij/psi/templateLanguages/TemplateDataElementType.java @@ -213,7 +213,11 @@ public class TemplateDataElementType extends IFileElementType implements ITempla return language; } }; + + // Since we're already inside a template language PSI that was built regardless of the file size (for whatever reason), + // there should also be no file size checks for template data files. SingleRootFileViewProvider.doNotCheckFileSizeLimit(virtualFile); + return viewProvider.getPsi(language); } diff --git a/platform/lang-impl/src/com/intellij/refactoring/BaseRefactoringProcessor.java b/platform/lang-impl/src/com/intellij/refactoring/BaseRefactoringProcessor.java index 41d37ca44770..bbd4fb83498d 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/BaseRefactoringProcessor.java +++ b/platform/lang-impl/src/com/intellij/refactoring/BaseRefactoringProcessor.java @@ -543,6 +543,7 @@ public abstract class BaseRefactoringProcessor implements Runnable { return; } if (ApplicationManager.getApplication().isWriteAccessAllowed()) { + LOG.info(new Exception()); DumbService.getInstance(myProject).smartInvokeLater(new Runnable() { @Override public void run() { diff --git a/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java index a933035c824f..722a942c4c7e 100644 --- a/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java +++ b/platform/lang-impl/src/com/intellij/refactoring/rename/RenameProcessor.java @@ -122,6 +122,7 @@ public class RenameProcessor extends BaseRefactoringProcessor { @Override public void doRun() { + if (!myPrimaryElement.isValid()) return; prepareRenaming(myPrimaryElement, myNewName, myAllRenames); super.doRun(); diff --git a/platform/lang-impl/testSources/com/intellij/psi/codeStyle/autodetect/DetectedIndentNotificationTest.java b/platform/lang-impl/testSources/com/intellij/psi/codeStyle/autodetect/DetectedIndentNotificationTest.java index 5eb9ac2ea00a..ac63de3a225e 100644 --- a/platform/lang-impl/testSources/com/intellij/psi/codeStyle/autodetect/DetectedIndentNotificationTest.java +++ b/platform/lang-impl/testSources/com/intellij/psi/codeStyle/autodetect/DetectedIndentNotificationTest.java @@ -21,6 +21,7 @@ import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsManager; import com.intellij.testFramework.PlatformTestCase; import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase; +import org.jetbrains.annotations.NotNull; public class DetectedIndentNotificationTest extends LightPlatformCodeInsightFixtureTestCase { @@ -63,13 +64,15 @@ public class DetectedIndentNotificationTest extends LightPlatformCodeInsightFixt PsiFile file = myFixture.getFile(); VirtualFile vFile = file.getVirtualFile(); - Boolean notificationShown = vFile.getUserData(DetectedIndentOptionsNotificationProvider.DETECT_INDENT_NOTIFICATION_SHOWN_KEY); - assert notificationShown == null; - - myFixture.type('\n'); - - notificationShown = vFile.getUserData(DetectedIndentOptionsNotificationProvider.DETECT_INDENT_NOTIFICATION_SHOWN_KEY); - assert notificationShown != null && notificationShown; + try { + vFile.putUserData(DetectedIndentOptionsNotificationProvider.SHOW_NOTIFICATION_IN_TEST, Boolean.TRUE); + assert !isNotificationShown(vFile); + myFixture.type('\n'); + assert isNotificationShown(vFile); + } + finally { + vFile.putUserData(DetectedIndentOptionsNotificationProvider.SHOW_NOTIFICATION_IN_TEST, null); + } } public void testNoNotification_WhenNothingDetected() throws Exception { @@ -84,13 +87,18 @@ public class DetectedIndentNotificationTest extends LightPlatformCodeInsightFixt PsiFile file = myFixture.getFile(); VirtualFile vFile = file.getVirtualFile(); - Boolean notificationShown = vFile.getUserData(DetectedIndentOptionsNotificationProvider.DETECT_INDENT_NOTIFICATION_SHOWN_KEY); - assert notificationShown == null; - - myFixture.type('\n'); - - notificationShown = vFile.getUserData(DetectedIndentOptionsNotificationProvider.DETECT_INDENT_NOTIFICATION_SHOWN_KEY); - assert notificationShown == null; + try { + vFile.putUserData(DetectedIndentOptionsNotificationProvider.SHOW_NOTIFICATION_IN_TEST, Boolean.TRUE); + assert !isNotificationShown(vFile); + myFixture.type('\n'); + assert !isNotificationShown(vFile); + } + finally { + vFile.putUserData(DetectedIndentOptionsNotificationProvider.SHOW_NOTIFICATION_IN_TEST, null); + } } + private boolean isNotificationShown(@NotNull VirtualFile vFile) { + return vFile.getUserData(DetectedIndentOptionsNotificationProvider.DETECT_INDENT_NOTIFICATION_SHOWN_KEY) != null; + } } diff --git a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java index 12f2211a592d..dc043f1b851a 100644 --- a/platform/platform-api/src/com/intellij/ide/BrowserUtil.java +++ b/platform/platform-api/src/com/intellij/ide/BrowserUtil.java @@ -21,10 +21,12 @@ import com.intellij.ide.browsers.BrowserLauncher; import com.intellij.ide.browsers.BrowserLauncherAppless; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -52,6 +54,13 @@ public class BrowserUtil { private static final Pattern ourExternalPrefix = Pattern.compile("^[\\w\\+\\.\\-]{2,}:"); private static final Pattern ourAnchorSuffix = Pattern.compile("#(.*)$"); + private static final Condition BROWSABLE_URL = new Condition() { + @Override + public boolean value(String s) { + return canBeBrowsed(s); + } + }; + private BrowserUtil() { } public static boolean isAbsoluteURL(String url) { @@ -62,6 +71,12 @@ public class BrowserUtil { return url != null && !url.startsWith("jar:"); } + @Nullable + public static List retainBrowsableUrls(@Nullable List urls) { + return urls == null ? null : ContainerUtil.filter(urls, BROWSABLE_URL); + } + + public static String getDocURL(String url) { Matcher anchorMatcher = ourAnchorSuffix.matcher(url); return anchorMatcher.find() ? anchorMatcher.reset().replaceAll("") : url; diff --git a/platform/platform-api/src/com/intellij/notification/Notification.java b/platform/platform-api/src/com/intellij/notification/Notification.java index 82e1615243e9..ccf2d559732f 100644 --- a/platform/platform-api/src/com/intellij/notification/Notification.java +++ b/platform/platform-api/src/com/intellij/notification/Notification.java @@ -43,7 +43,7 @@ public class Notification { private Runnable myWhenExpired; private Boolean myImportant; private WeakReference myBalloonRef; - private long myTimestamp; + private final long myTimestamp; public Notification(@NotNull String groupDisplayId, @NotNull String title, @NotNull String content, @NotNull NotificationType type) { this(groupDisplayId, title, content, type, null); diff --git a/platform/platform-api/src/com/intellij/openapi/vfs/JarFileSystem.java b/platform/platform-api/src/com/intellij/openapi/vfs/JarFileSystem.java index df5b07173bd8..d99e9f009556 100644 --- a/platform/platform-api/src/com/intellij/openapi/vfs/JarFileSystem.java +++ b/platform/platform-api/src/com/intellij/openapi/vfs/JarFileSystem.java @@ -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 diff --git a/platform/platform-impl/src/com/intellij/help/impl/HelpManagerImpl.java b/platform/platform-impl/src/com/intellij/help/impl/HelpManagerImpl.java index 8d8fa2d6797b..f743059eeb12 100644 --- a/platform/platform-impl/src/com/intellij/help/impl/HelpManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/help/impl/HelpManagerImpl.java @@ -29,6 +29,7 @@ import com.intellij.openapi.help.HelpManager; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.registry.Registry; +import com.intellij.util.PlatformUtils; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; @@ -66,7 +67,19 @@ public class HelpManagerImpl extends HelpManager { } if (myHelpSet == null) { - BrowserUtil.browse(ApplicationInfoEx.getInstanceEx().getWebHelpUrl() + "?" + id); + ApplicationInfoEx info = ApplicationInfoEx.getInstanceEx(); + String url = info.getWebHelpUrl() + "?"; + if (PlatformUtils.isCLion()) { + url += "Keyword=" + id; + url += "&ProductVersion=" + info.getMajorVersion() + "." + info.getMinorVersion(); + + if (info.isEAP()) { + url += "&EAP"; + } + } else { + url += id; + } + BrowserUtil.browse(url); return; } diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/LaterInvocator.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/LaterInvocator.java index fb99c5c9af7f..f58965e756d4 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/LaterInvocator.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/LaterInvocator.java @@ -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. @@ -51,22 +51,21 @@ public class LaterInvocator { private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.application.impl.LaterInvocator"); private static final boolean DEBUG = LOG.isDebugEnabled(); - public static final Object LOCK = new Object(); //public for tests + private static final Object LOCK = new Object(); private static final IdeEventQueue ourEventQueue = IdeEventQueue.getInstance(); private static final FrequentEventDetector ourFrequentEventDetector = new FrequentEventDetector(1009, 100); - private LaterInvocator() { - } + private LaterInvocator() { } private static class RunnableInfo { @NotNull private final Runnable runnable; @NotNull private final ModalityState modalityState; - @NotNull private final Condition expired; + @NotNull private final Condition expired; @NotNull private final ActionCallback callback; public RunnableInfo(@NotNull Runnable runnable, @NotNull ModalityState modalityState, - @NotNull Condition expired, + @NotNull Condition expired, @NotNull ActionCallback callback) { this.runnable = runnable; this.modalityState = modalityState; @@ -101,7 +100,9 @@ public class LaterInvocator { int index = ourModalEntities.indexOf(window); if (index < 0) { Window owner = window.getOwner(); - if (owner == null) return (ModalityStateEx)ApplicationManager.getApplication().getNoneModalityState(); + if (owner == null) { + return (ModalityStateEx)ApplicationManager.getApplication().getNoneModalityState(); + } ModalityStateEx ownerState = modalityStateForWindow(owner); if (window instanceof Dialog && ((Dialog)window).isModal()) { return ownerState.appendEntity(window); @@ -109,22 +110,18 @@ public class LaterInvocator { return ownerState; } - ArrayList result = new ArrayList(); + List result = new ArrayList(); for (Object entity : ourModalEntities) { - if (entity instanceof Window) { + if (entity instanceof Window || + entity instanceof ProgressIndicator && ((ProgressIndicator)entity).isModal()) { result.add(entity); } - else if (entity instanceof ProgressIndicator) { - if (((ProgressIndicator)entity).isModal()) { - result.add(entity); - } - } } return new ModalityStateEx(result.toArray()); } @NotNull - static ActionCallback invokeLater(@NotNull Runnable runnable, @NotNull Condition expired) { + static ActionCallback invokeLater(@NotNull Runnable runnable, @NotNull Condition expired) { ModalityState modalityState = ModalityState.defaultModalityState(); return invokeLater(runnable, modalityState, expired); } @@ -135,9 +132,7 @@ public class LaterInvocator { } @NotNull - static ActionCallback invokeLater(@NotNull Runnable runnable, - @NotNull ModalityState modalityState, - @NotNull Condition expired) { + static ActionCallback invokeLater(@NotNull Runnable runnable, @NotNull ModalityState modalityState, @NotNull Condition expired) { ourFrequentEventDetector.eventHappened(); final ActionCallback callback = new ActionCallback(); @@ -332,13 +327,8 @@ public class LaterInvocator { lastInfo.runnable.run(); lastInfo.callback.setDone(); } - catch (ProcessCanceledException ex) { - // ignore - } + catch (ProcessCanceledException ignored) { } catch (Throwable t) { - if (t instanceof StackOverflowError) { - t.printStackTrace(); - } LOG.error(t); } finally { @@ -354,9 +344,8 @@ public class LaterInvocator { } @Override - @NonNls public String toString() { - return "LaterInvocator.FlushQueue" + (myLastInfo == null ? "" : " lastInfo="+myLastInfo); + return "LaterInvocator.FlushQueue" + (myLastInfo == null ? "" : " lastInfo=" + myLastInfo); } } @@ -366,20 +355,4 @@ public class LaterInvocator { return ContainerUtil.newArrayList(ourQueue); } } - - @TestOnly - static String dumpQueue() { - synchronized (LOCK) { - @NonNls String result = ""; - if (!ourForcedFlushQueue.isEmpty()) { - result = "(Forced queue: " + ourForcedFlushQueue + ") "; - } - List r = new ArrayList(ourQueue); - result += r + (ourQueueSkipCount == 0 ? "" : " (ourQueueSkipCount="+ourQueueSkipCount+")") - + (ourModalEntities.isEmpty() ? " (non-modal)" : " (modal entities: "+ourModalEntities+")" - + (FLUSHER_SCHEDULED.get() ? " (Flusher scheduled)" : "") - ); - return result; - } - } } diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/ModalityInvokatorImpl.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/ModalityInvokatorImpl.java index 07b55a6e4010..dbb164ea7cac 100644 --- a/platform/platform-impl/src/com/intellij/openapi/application/impl/ModalityInvokatorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/ModalityInvokatorImpl.java @@ -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. @@ -13,10 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -/* - * @author max - */ package com.intellij.openapi.application.impl; import com.intellij.openapi.application.ApplicationManager; @@ -26,9 +22,11 @@ import com.intellij.openapi.util.ActionCallback; import com.intellij.openapi.util.Condition; import org.jetbrains.annotations.NotNull; +/** + * @author max + */ class ModalityInvokatorImpl implements ModalityInvokator { - ModalityInvokatorImpl() { - } + ModalityInvokatorImpl() { } @NotNull @Override @@ -38,13 +36,13 @@ class ModalityInvokatorImpl implements ModalityInvokator { @NotNull @Override - public ActionCallback invokeLater(@NotNull final Runnable runnable, @NotNull final Condition expired) { + public ActionCallback invokeLater(@NotNull Runnable runnable, @NotNull Condition expired) { return LaterInvocator.invokeLater(runnable, expired); } @NotNull @Override - public ActionCallback invokeLater(@NotNull final Runnable runnable, @NotNull final ModalityState state, @NotNull final Condition expired) { + public ActionCallback invokeLater(@NotNull Runnable runnable, @NotNull ModalityState state, @NotNull Condition expired) { return LaterInvocator.invokeLater(runnable, state, expired); } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/ServiceManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/ServiceManagerImpl.java index 05ce99453036..8b04f9cd8623 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/ServiceManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/ServiceManagerImpl.java @@ -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"); } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java index 5d0dcf7d2e11..74270496bed6 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/ComponentStoreImpl.java @@ -299,8 +299,7 @@ public abstract class ComponentStoreImpl implements IComponentStore.Reloadable { } Class stateClass = ComponentSerializationUtil.getStateClass(component.getClass()); - // todo remove assert before last EAP - if (!stateSpec.defaultStateAsResource() && getDefaultState(component, name, stateClass) != null) { + if (LOG.isDebugEnabled()) { LOG.error(name + " has default state, but not marked to load it"); } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java index 903596282727..08afd8c711c1 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java @@ -137,15 +137,14 @@ public class StorageUtil { boolean equals = isEqualContent(result, lineSeparatorIfPrependXmlProlog, content); if (equals) { LOG.warn("Content equals, but it must be handled not on this level — " + result.getName()); - return result; } else { if (ApplicationManager.getApplication().isUnitTestMode() && DEBUG_LOG != null) { DEBUG_LOG = result.getPath() + ":\n" + content+"\nOld Content:\n"+ LoadTextUtil.loadText(result)+"\n---------"; } doWrite(requestor, result, virtualFile, content, lineSeparatorIfPrependXmlProlog); - return result; } + return result; } @TestOnly diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorComponentImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorComponentImpl.java index 866bc141d47f..c1179c5bd488 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorComponentImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorComponentImpl.java @@ -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,33 +15,45 @@ */ package com.intellij.openapi.editor.impl; +import com.intellij.ide.CutProvider; +import com.intellij.ide.DataManager; import com.intellij.ide.IdeEventQueue; +import com.intellij.ide.PasteProvider; import com.intellij.ide.ui.UISettings; import com.intellij.openapi.actionSystem.CommonDataKeys; +import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.actionSystem.DataProvider; import com.intellij.openapi.actionSystem.PlatformDataKeys; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.impl.ApplicationImpl; import com.intellij.openapi.editor.VisualPosition; import com.intellij.openapi.editor.colors.EditorColorsManager; +import com.intellij.openapi.editor.event.CaretEvent; +import com.intellij.openapi.editor.event.CaretListener; +import com.intellij.openapi.editor.event.DocumentListener; import com.intellij.openapi.editor.ex.util.EditorUtil; import com.intellij.openapi.ui.Queryable; import com.intellij.openapi.ui.TypingTarget; import com.intellij.openapi.util.ActionCallback; +import com.intellij.openapi.util.TextRange; import com.intellij.ui.Grayer; import com.intellij.ui.components.Magnificator; import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; +import javax.accessibility.*; import javax.swing.*; +import javax.swing.event.DocumentEvent; +import javax.swing.text.AttributeSet; import java.awt.*; +import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.awt.event.InputMethodEvent; import java.awt.im.InputMethodRequests; import java.util.Map; -public class EditorComponentImpl extends JComponent implements Scrollable, DataProvider, Queryable, TypingTarget { +public class EditorComponentImpl extends JComponent implements Scrollable, DataProvider, Queryable, TypingTarget, Accessible { private final EditorImpl myEditor; private final ApplicationImpl myApplication; @@ -232,4 +244,297 @@ public class EditorComponentImpl extends JComponent implements Scrollable, DataP public String toString() { return "EditorComponent file=" + myEditor.getVirtualFile(); } + + @Override + public AccessibleContext getAccessibleContext() { + if (accessibleContext == null) { + accessibleContext = new AccessibleEditor(); + } + return accessibleContext; + } + + /** + * @author Konstantin Bulenkov + */ + protected class AccessibleEditor extends AccessibleJComponent implements AccessibleText, AccessibleAction, AccessibleEditableText, + AccessibleExtendedText, CaretListener, DocumentListener { + + int caretPos; + Point oldLocationOnScreen; + + public AccessibleEditor() { + getEditor().getDocument().addDocumentListener(this); + getEditor().getCaretModel().addCaretListener(this); + caretPos = getCaretPosition(); + + try { + oldLocationOnScreen = getLocationOnScreen(); + } + catch (IllegalComponentStateException iae) {// + } + + EditorComponentImpl.this.addComponentListener(new ComponentAdapter() { + + public void componentMoved(ComponentEvent e) { + try { + Point newLocationOnScreen = getLocationOnScreen(); + firePropertyChange(ACCESSIBLE_VISIBLE_DATA_PROPERTY, oldLocationOnScreen, newLocationOnScreen); + oldLocationOnScreen = newLocationOnScreen; + } + catch (IllegalComponentStateException iae) {// + } + } + }); + } + + public void caretUpdate(CaretEvent e) { + //int dot = e.getDot(); + //int mark = e.getMark(); + //if (caretPos != dot) { + // // the caret moved + // firePropertyChange(ACCESSIBLE_CARET_PROPERTY, new Integer(caretPos), new Integer(dot)); + // caretPos = dot; + // + // try { + // oldLocationOnScreen = getLocationOnScreen(); + // } + // catch (IllegalComponentStateException iae) {// + // } + //} + //if (mark != dot) { + // // there is a selection + // firePropertyChange(ACCESSIBLE_SELECTION_PROPERTY, null, getSelectedText()); + //} + } + + + public void insertUpdate(DocumentEvent e) { + documentUpdated(e.getOffset()); + } + + protected void documentUpdated(int index) { + final Integer offset = new Integer(index); + if (SwingUtilities.isEventDispatchThread()) { + firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null, offset); + } + else { + //noinspection SSBasedInspection + SwingUtilities.invokeLater(new Runnable() { + public void run() { + firePropertyChange(ACCESSIBLE_TEXT_PROPERTY, null, offset); + } + }); + } + } + + public void removeUpdate(DocumentEvent e) { + documentUpdated(e.getOffset()); + } + + public void changedUpdate(DocumentEvent e) { + documentUpdated(e.getOffset()); + } + + + public AccessibleStateSet getAccessibleStateSet() { + AccessibleStateSet states = super.getAccessibleStateSet(); + if (!EditorComponentImpl.this.getEditor().isViewer()) { + states.add(AccessibleState.EDITABLE); + } + if (!getEditor().isOneLineMode()) { + states.add(AccessibleState.MULTI_LINE); + } + return states; + } + + public AccessibleRole getAccessibleRole() { + return AccessibleRole.TEXT; + } + + public AccessibleText getAccessibleText() { + return this; + } + + public int getIndexAtPoint(Point p) { + if (p == null) { + return -1; + } + final EditorImpl editor = EditorComponentImpl.this.getEditor(); + return editor.logicalPositionToOffset(editor.xyToLogicalPosition(p)); + } + + public Rectangle getCharacterBounds(int i) { + final EditorImpl editor = EditorComponentImpl.this.getEditor(); + final Point point = editor.offsetToXY(i, true); + //todo[kb] more accurate calculation here + final int width = editor.getFontMetrics(Font.PLAIN).charWidth(editor.getDocument().getText().charAt(i)); + return new Rectangle(point, new Dimension(width, editor.getLineHeight())); + } + + public int getCharCount() { + return getEditor().getDocument().getTextLength(); + } + + + public int getCaretPosition() { + return getEditor().getCaretModel().getOffset(); + } + + public AttributeSet getCharacterAttribute(int i) { + return null; //todo[kb] + } + + public int getSelectionStart() { + return getEditor().getSelectionModel().getSelectionStart(); + } + + public int getSelectionEnd() { + return getEditor().getSelectionModel().getSelectionEnd(); + } + + public String getSelectedText() { + return getEditor().getSelectionModel().getSelectedText(); + } + + @Override + public void caretPositionChanged(CaretEvent e) { + caretUpdate(e); + } + + @Override + public void caretAdded(CaretEvent e) { + caretUpdate(e); + } + + @Override + public void caretRemoved(CaretEvent e) { + caretUpdate(e); + } + + @Override + public void beforeDocumentChange(com.intellij.openapi.editor.event.DocumentEvent event) { + + } + + @Override + public void documentChanged(com.intellij.openapi.editor.event.DocumentEvent event) { + documentUpdated(event.getOffset()); + } + + public String getAtIndex(int part, int index) { + return getAtIndex(part, index, 0); + } + + public String getAfterIndex(int part, int index) { + return getAtIndex(part, index, 1); + } + + public String getBeforeIndex(int part, int index) { + return getAtIndex(part, index, -1); + } + + private String getAtIndex(int part, int index, int direction) { + return "?"; //todo + } + + public AccessibleEditableText getAccessibleEditableText() { + return this; + } + + public void setTextContents(String s) { + getEditor().getDocument().setText(s); + } + + + public void insertTextAtIndex(int index, String s) { + getEditor().getDocument().insertString(index, s); + } + + public String getTextRange(int startIndex, int endIndex) { + return getEditor().getDocument().getText(TextRange.create(startIndex, endIndex)); + } + + public void delete(int startIndex, int endIndex) { + if (!getEditor().isViewer()) { + getEditor().getDocument().deleteString(startIndex, endIndex); + } + else { + UIManager.getLookAndFeel().provideErrorFeedback(EditorComponentImpl.this); + } + } + + public void cut(int startIndex, int endIndex) { + selectText(startIndex, endIndex); + final DataContext context = DataManager.getInstance().getDataContext(EditorComponentImpl.this); + final CutProvider cutProvider = getEditor().getCutProvider(); + if (cutProvider.isCutEnabled(context)) { + cutProvider.performCut(context); + } + } + + public void paste(int startIndex) { + getEditor().getCaretModel().moveToOffset(startIndex); + final PasteProvider pasteProvider = getEditor().getPasteProvider(); + final DataContext context = DataManager.getInstance().getDataContext(EditorComponentImpl.this); + if (pasteProvider.isPasteEnabled(context)) { + pasteProvider.performPaste(context); + } + } + + public void replaceText(int startIndex, int endIndex, String s) { + getEditor().getDocument().replaceString(startIndex, endIndex, s); + } + + public void selectText(int startIndex, int endIndex) { + getEditor().getSelectionModel().setSelection(startIndex, endIndex); + } + + public void setAttributes(int startIndex, int endIndex, AttributeSet as) { + //todo[kb] not supported? + } + + private AccessibleTextSequence getSequenceAtIndex(int part, int index, int direction) { + //todo[kb] + return null; + } + + + public AccessibleTextSequence getTextSequenceAt(int part, int index) { + return getSequenceAtIndex(part, index, 0); + } + + public AccessibleTextSequence getTextSequenceAfter(int part, int index) { + return getSequenceAtIndex(part, index, 1); + } + + public AccessibleTextSequence getTextSequenceBefore(int part, int index) { + return getSequenceAtIndex(part, index, -1); + } + + public Rectangle getTextBounds(int startIndex, int endIndex) { + final Point start = getEditor().offsetToXY(startIndex, true); + final Point end = getEditor().offsetToXY(endIndex, true); + if (start.y == end.y) { + return new Rectangle(start, new Dimension(end.x - start.x, getEditor().getLineHeight())); + } + final int width = getEditor().getMaxWidthInRange(startIndex, endIndex); + return new Rectangle(start, new Dimension(width, end.y - start.y + getEditor().getLineHeight())); + } + + public AccessibleAction getAccessibleAction() { + return this; + } + + public int getAccessibleActionCount() { + return 0; + } + + public String getAccessibleActionDescription(int i) { + return null; + } + + public boolean doAccessibleAction(int i) { + return false; + } + } } diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java index 939eace5d54d..187364b26f36 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java @@ -20,10 +20,7 @@ import com.intellij.ide.IdeBundle; import com.intellij.ide.plugins.*; import com.intellij.ide.util.PropertiesComponent; import com.intellij.notification.*; -import com.intellij.openapi.application.ApplicationInfo; -import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.application.ApplicationNamesInfo; -import com.intellij.openapi.application.PathManager; +import com.intellij.openapi.application.*; import com.intellij.openapi.application.ex.ApplicationInfoEx; import com.intellij.openapi.diagnostic.IdeaLoggingEvent; import com.intellij.openapi.diagnostic.LogUtil; @@ -200,7 +197,7 @@ public final class UpdateChecker { callback.setDone(); } } - }); + }, ModalityState.NON_MODAL); } @NotNull diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/DummyFileSystem.java b/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/DummyFileSystem.java index ec03da0c2342..8ed06b776d39 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/DummyFileSystem.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/ex/dummy/DummyFileSystem.java @@ -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(); diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemBase.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemBase.java index a2d32fd1307f..bbbfd18d93c5 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemBase.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/http/HttpFileSystemBase.java @@ -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) { diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/UserDataInterner.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/UserDataInterner.java index ad2e490d3784..0c5b331ad89c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/UserDataInterner.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/UserDataInterner.java @@ -15,30 +15,116 @@ */ package com.intellij.openapi.vfs.newvfs.impl; -import com.intellij.util.ConcurrencyUtil; -import com.intellij.util.containers.ContainerUtil; +import com.intellij.reference.SoftReference; +import com.intellij.util.containers.hash.LinkedHashMap; +import com.intellij.util.keyFMap.ArrayBackedFMap; import com.intellij.util.keyFMap.KeyFMap; import com.intellij.util.keyFMap.OneElementFMap; +import com.intellij.util.keyFMap.PairElementsFMap; import org.jetbrains.annotations.NotNull; -import java.nio.charset.Charset; -import java.util.concurrent.ConcurrentMap; +import java.lang.ref.WeakReference; +import java.util.Arrays; +import java.util.Map; /** * @author peter */ class UserDataInterner { - private static final ConcurrentMap ourCache = ContainerUtil.createConcurrentWeakMap(); - + private static final LinkedHashMap ourCache = new LinkedHashMap(20, true) { + @Override + protected boolean removeEldestEntry(Map.Entry eldest) { + return size() > 15; + } + }; + static KeyFMap internUserData(@NotNull KeyFMap map) { - if (map instanceof OneElementFMap && shouldIntern((OneElementFMap)map)) { - return ConcurrencyUtil.cacheOrGet(ourCache, (OneElementFMap)map, (OneElementFMap)map); + if (shouldIntern(map)) { + MapReference key = new MapReference(map); + synchronized (ourCache) { + KeyFMap cached = SoftReference.dereference(ourCache.get(key)); + if (cached != null) return cached; + + ourCache.put(key, key); + } + return map; } return map; } - private static boolean shouldIntern(OneElementFMap map) { - Object value = map.getValue(); - return value instanceof Enum || value instanceof Boolean || value instanceof Charset; + private static boolean shouldIntern(@NotNull KeyFMap map) { + return map instanceof OneElementFMap || + map instanceof PairElementsFMap || + map instanceof ArrayBackedFMap && ((ArrayBackedFMap)map).getKeys().length <= 5; + } +} + +class MapReference extends WeakReference { + final int myHash; + + MapReference(KeyFMap referent) { + super(referent); + myHash = computeHashCode(referent); + } + + private static int computeHashCode(KeyFMap object) { + if (object instanceof OneElementFMap) { + return ((OneElementFMap)object).getKey().hashCode() * 31 + System.identityHashCode(((OneElementFMap)object).getValue()); + } + if (object instanceof PairElementsFMap) { + PairElementsFMap map = (PairElementsFMap)object; + return (map.getKey1().hashCode() * 31 + map.getKey2().hashCode()) * 31 + + System.identityHashCode(map.getValue1()) + System.identityHashCode(map.getValue2()); + } + if (object instanceof ArrayBackedFMap) { + int hc = Arrays.hashCode(((ArrayBackedFMap)object).getKeys()); + for (Object o : ((ArrayBackedFMap)object).getValues()) { + hc = hc * 31 + System.identityHashCode(o); + } + return hc; + } + return 0; + } + + @Override + public int hashCode() { + return myHash; + } + + @Override + public boolean equals(Object obj) { + if (obj == this) return true; + if (!(obj instanceof MapReference) || myHash != ((MapReference)obj).myHash) return false; + + KeyFMap o1 = get(); + KeyFMap o2 = ((MapReference)obj).get(); + if (o1 == null || o2 == null) return false; + + if (o1 instanceof OneElementFMap && o2 instanceof OneElementFMap) { + OneElementFMap m1 = (OneElementFMap)o1; + OneElementFMap m2 = (OneElementFMap)o2; + return m1.getKey() == m2.getKey() && m1.getValue() == m2.getValue(); + } + if (o1 instanceof PairElementsFMap && o2 instanceof PairElementsFMap) { + PairElementsFMap m1 = (PairElementsFMap)o1; + PairElementsFMap m2 = (PairElementsFMap)o2; + return m1.getKey1() == m2.getKey1() && m1.getKey2() == m2.getKey2() && + m1.getValue1() == m2.getValue1() && m1.getValue2() == m2.getValue2(); + } + if (o1 instanceof ArrayBackedFMap && o2 instanceof ArrayBackedFMap) { + ArrayBackedFMap m1 = (ArrayBackedFMap)o1; + ArrayBackedFMap m2 = (ArrayBackedFMap)o2; + return Arrays.equals(m1.getKeys(), m2.getKeys()) && containSameElements(m1.getValues(), m2.getValues()); + } + return false; + } + + private static boolean containSameElements(Object[] v1, Object[] v2) { + if (v1.length != v2.length) return false; + + for (int i = 0; i < v1.length; i++) { + if (v1[i] != v2[i]) return false; + } + return true; } } diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VfsRootAccess.java b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VfsRootAccess.java index fa18bc1dc451..aa900b5f6c7b 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VfsRootAccess.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/newvfs/impl/VfsRootAccess.java @@ -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) { diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java index 3dfbe464e517..9d80e5a5746c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/IdeFrameImpl.java @@ -422,7 +422,7 @@ public class IdeFrameImpl extends JFrame implements IdeFrameEx, DataProvider { final LineSeparatorPanel lineSeparatorPanel = new LineSeparatorPanel(project); statusBar.addWidget(lineSeparatorPanel, "before " + encodingPanel.ID()); - final ToggleReadOnlyAttributePanel readOnlyAttributePanel = new ToggleReadOnlyAttributePanel(); + final ToggleReadOnlyAttributePanel readOnlyAttributePanel = new ToggleReadOnlyAttributePanel(project); final InsertOverwritePanel insertOverwritePanel = new InsertOverwritePanel(project); statusBar.addWidget(insertOverwritePanel, "after Encoding"); diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java index 73b68274c8c2..d5a7e920ffc0 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/InfoAndProgressPanel.java @@ -586,6 +586,11 @@ public class InfoAndProgressPanel extends JPanel implements CustomStatusBarWidge add(myRefreshAndInfoPanel, BorderLayout.CENTER); myProgressIcon.suspend(); + Container iconParent = myProgressIcon.getParent(); + if (iconParent != null) { + iconParent.remove(myProgressIcon); // to prevent leaks to this removed parent via progress icon + } + myRefreshAndInfoPanel.revalidate(); myRefreshAndInfoPanel.repaint(); } diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/MemoryUsagePanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/MemoryUsagePanel.java index dd879da7e8c9..d6039a5f205e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/MemoryUsagePanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/MemoryUsagePanel.java @@ -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. @@ -138,7 +138,7 @@ public class MemoryUsagePanel extends JButton implements CustomStatusBarWidget { final int totalBarLength = size.width - insets.left - insets.right; final int usedBarLength = (int)(totalBarLength * usedMem / maxMem); final int unusedBarLength = (int)(totalBarLength * unusedMem / maxMem); - final int barHeight = HEIGHT; + final int barHeight = Math.max(JBUI.scale(HEIGHT), getFont().getSize() + 2); final int yOffset = (size.height - barHeight) / 2; final int xOffset = insets.left; diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToggleReadOnlyAttributePanel.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToggleReadOnlyAttributePanel.java index 3b89e81eb1f5..98c5aee6653d 100644 --- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToggleReadOnlyAttributePanel.java +++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/status/ToggleReadOnlyAttributePanel.java @@ -19,7 +19,7 @@ import com.intellij.icons.AllIcons; import com.intellij.ide.DataManager; import com.intellij.openapi.actionSystem.CommonDataKeys; import com.intellij.openapi.application.ApplicationManager; -import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.fileEditor.*; import com.intellij.openapi.fileEditor.ex.FileEditorManagerEx; import com.intellij.openapi.fileEditor.impl.EditorsSplitters; import com.intellij.openapi.project.Project; @@ -30,6 +30,7 @@ import com.intellij.openapi.wm.StatusBarWidget; import com.intellij.ui.UIBundle; import com.intellij.util.Consumer; import com.intellij.util.io.ReadOnlyAttributeUtil; +import com.intellij.util.messages.MessageBusConnection; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -37,10 +38,17 @@ import javax.swing.*; import java.awt.event.MouseEvent; import java.io.IOException; -public class ToggleReadOnlyAttributePanel implements StatusBarWidget.Multiframe, StatusBarWidget.IconPresentation { - +public class ToggleReadOnlyAttributePanel extends FileEditorManagerAdapter implements StatusBarWidget.Multiframe, + StatusBarWidget.IconPresentation{ + private Project myProject; private StatusBar myStatusBar; + public ToggleReadOnlyAttributePanel(@NotNull Project project) { + myProject = project; + MessageBusConnection connection = project.getMessageBus().connect(this); + connection.subscribe(FileEditorManagerListener.FILE_EDITOR_MANAGER, this); + } + @NotNull public Icon getIcon() { VirtualFile virtualFile = getCurrentFile(); @@ -55,7 +63,7 @@ public class ToggleReadOnlyAttributePanel implements StatusBarWidget.Multiframe, @Override public StatusBarWidget copy() { - return new ToggleReadOnlyAttributePanel(); + return new ToggleReadOnlyAttributePanel(myProject); } public WidgetPresentation getPresentation(@NotNull PlatformType type) { @@ -64,6 +72,7 @@ public class ToggleReadOnlyAttributePanel implements StatusBarWidget.Multiframe, public void dispose() { myStatusBar = null; + myProject = null; } public void install(@NotNull StatusBar statusBar) { @@ -119,4 +128,9 @@ public class ToggleReadOnlyAttributePanel implements StatusBarWidget.Multiframe, EditorsSplitters splitters = FileEditorManagerEx.getInstanceEx(project).getSplittersFor(myStatusBar.getComponent()); return splitters.getCurrentFile(); } + + @Override + public void selectionChanged(@NotNull FileEditorManagerEvent event) { + myStatusBar.updateWidget(ID()); + } } diff --git a/platform/platform-resources-en/src/messages/ExecutionBundle.properties b/platform/platform-resources-en/src/messages/ExecutionBundle.properties index 6ce5d64c70bd..74706713600d 100644 --- a/platform/platform-resources-en/src/messages/ExecutionBundle.properties +++ b/platform/platform-resources-en/src/messages/ExecutionBundle.properties @@ -207,7 +207,8 @@ failed.to.generate.wrapper.error.message=Failed to generate temporary html wrapp application.configuration.use.classpath.and.jdk.of.module.label=Use classpath of m&odule: application.configuration.main.class.label=Main &class: -jre.path.is.not.valid.jre.home.error.mesage=''{0}'' is not a valid JRE home +jre.path.is.not.valid.jre.home.error.message=''{0}'' is not a valid JRE home +jre.path.is.jdk.error.message=Alternative JRE path needs to point to a JRE, not to a complete JDK installation main.method.not.found.in.class.error.message=Main method not found in class {0} no.user.process.input.error.message=No process input fix.run.configuration.problem.button=Fix diff --git a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/ServersTreeStructure.java b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/ServersTreeStructure.java index 8907efc52e59..29c02383df32 100644 --- a/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/ServersTreeStructure.java +++ b/platform/remote-servers/impl/src/com/intellij/remoteServer/impl/runtime/ui/tree/ServersTreeStructure.java @@ -182,17 +182,17 @@ public class ServersTreeStructure extends AbstractTreeStructureBase { final RemoteServer server = getValue(); final ServerType serverType = server.getType(); final DeploymentConfigurationManager configurationManager = DeploymentConfigurationManager.getInstance(doGetProject()); - List list - = ContainerUtil.filter(configurationManager.getDeploymentConfigurations(serverType), - new Condition() { - - @Override - public boolean value(RunnerAndConfigurationSettings settings) { - DeployToServerRunConfiguration configuration = - (DeployToServerRunConfiguration)settings.getConfiguration(); - return StringUtil.equals(server.getName(), configuration.getServerName()); - } - }); + final List list = new ArrayList(ContainerUtil.filter( + configurationManager.getDeploymentConfigurations(serverType), + new Condition() { + @Override + public boolean value(RunnerAndConfigurationSettings settings) { + DeployToServerRunConfiguration configuration = + (DeployToServerRunConfiguration)settings.getConfiguration(); + return StringUtil.equals(server.getName(), configuration.getServerName()); + } + } + )); if (canCreate) { list.add(null); } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/XmlStructuralSearchProfile.java b/platform/structuralsearch/source/com/intellij/structuralsearch/XmlStructuralSearchProfile.java index b2f83df3f855..5882e2f69f4f 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/XmlStructuralSearchProfile.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/XmlStructuralSearchProfile.java @@ -212,7 +212,8 @@ public class XmlStructuralSearchProfile extends StructuralSearchProfile { createSearchTemplateInfo("xml attribute value", "<'_tag '_attribute=\"'value\"/>", HTML_XML, StdFileTypes.XML), createSearchTemplateInfo("html attribute value", "<'_tag '_attribute='value />", HTML_XML, StdFileTypes.HTML), createSearchTemplateInfo("xml/html tag value", "'_content*
", HTML_XML, StdFileTypes.HTML), - //createSearchTemplateInfo("li not contained in ul/ol", "[!within( \"<'_tag:[regex( \"ul|ol\" )] />\" )]
  • ", HTML_XML, StdFileTypes.HTML) + createSearchTemplateInfo("
  • not contained in
      or
        ", "[!within( \"<'_tag:[regex( ul|ol )] />\" )]
      1. ", + HTML_XML, StdFileTypes.HTML) }; } } diff --git a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/StringToConstraintsTransformer.java b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/StringToConstraintsTransformer.java index bebf1c94fbcc..f5732ab0d050 100644 --- a/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/StringToConstraintsTransformer.java +++ b/platform/structuralsearch/source/com/intellij/structuralsearch/impl/matcher/compiler/StringToConstraintsTransformer.java @@ -4,9 +4,8 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.structuralsearch.*; import com.intellij.structuralsearch.plugin.ui.Configuration; import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; -import java.util.List; -import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.regex.PatternSyntaxException; @@ -18,12 +17,6 @@ import java.util.regex.PatternSyntaxException; * To change this template use File | Settings | File Templates. */ class StringToConstraintsTransformer { - @NonNls private static final String P_STR = "(\\w+)\\('(\\w+)\\)"; - private static final Pattern p = Pattern.compile(P_STR); - @NonNls private static final String P2_STR = "(\\w+)"; - private static final Pattern p2 = Pattern.compile(P2_STR); - @NonNls private static final String P3_STR = "(\\w+)\\(( ?(?:[\\\"\\*<>!\\.\\?\\:\\$\\\\\\(\\)\\[\\]\\w\\|\\+ =]*|(?:\\\"[^\\\"]*\\\")) ?)\\)"; - private static final Pattern p3 = Pattern.compile(P3_STR); @NonNls private static final String REF = "ref"; @NonNls private static final String READ = "read"; @NonNls private static final String WRITE = "write"; @@ -200,26 +193,25 @@ class StringToConstraintsTransformer { constraint.setGreedy(greedy); constraint.setPartOfSearchResults(!anonymous); if (targetFound && !anonymous) { - throw new MalformedPatternException("Only one target allowed"); + throw new MalformedPatternException(SSRBundle.message("error.only.one.target.allowed")); } targetFound = !anonymous; } else if (savedIndex != index) { - throw new MalformedPatternException("Constraints only allowed on first of variable"); + throw new MalformedPatternException(SSRBundle.message("error.condition.only.on.first.variable.reference")); } if (index < length && pattern.charAt(index) == ':') { ++index; - if (index >= length) throw new MalformedPatternException(SSRBundle.message("error.expected.condition", ':')); + if (index >= length) throw new MalformedPatternException(SSRBundle.message("error.expected.condition", ":")); ch = pattern.charAt(index); if (ch == ':') { // double colon instead of condition buf.append(ch); } else { - if (!constraintCreated) { - throw new MalformedPatternException("Constraints only allowed on first of variable"); - } + if (!constraintCreated) + throw new MalformedPatternException(SSRBundle.message("error.condition.only.on.first.variable.reference")); index = eatTypedVarCondition(index, pattern, miscBuffer, constraint); } } @@ -241,10 +233,7 @@ class StringToConstraintsTransformer { options.setSearchPattern( buf.toString() ); } - private static int eatTypedVarCondition(int index, - String pattern, - StringBuilder miscBuffer, - MatchVariableConstraint constraint) { + private static int eatTypedVarCondition(int index, String pattern, StringBuilder miscBuffer, MatchVariableConstraint constraint) { final int length = pattern.length(); char ch = pattern.charAt(index); @@ -266,27 +255,22 @@ class StringToConstraintsTransformer { if (ch == '[') { // eat complete condition - miscBuffer.setLength(0); - for(++index; index < length && ((ch = pattern.charAt(index)) != ']' || pattern.charAt(index-1) == '\\'); ++index) { - if (ch == '"') { - miscBuffer.append(ch); - for (++index; index < length && (ch = pattern.charAt(index)) != '"'; ++index) { - if (ch == '\\') { - ++index; - if (index >= length) break; - ch = pattern.charAt(index); - } - miscBuffer.append(ch); - } - if (ch != '"') throw new MalformedPatternException(SSRBundle.message("error.expected.end.quote")); + boolean quoted = false; + while (++index < length) { + ch = pattern.charAt(index); + if (pattern.charAt(index - 1) != '\\') { + if (ch == '"') quoted = !quoted; + else if (ch == ']' && !quoted) break; } miscBuffer.append(ch); } + if (quoted) throw new MalformedPatternException(SSRBundle.message("error.expected.value", "\"")); if (ch != ']') throw new MalformedPatternException(SSRBundle.message("error.expected.condition.or.bracket")); ++index; parseCondition(constraint, miscBuffer.toString()); - } else { + } + else { // eat reg exp constraint miscBuffer.setLength(0); index = handleRegExp(index, pattern, miscBuffer, constraint); @@ -309,16 +293,11 @@ class StringToConstraintsTransformer { else return index; String regexp = miscBuffer.toString(); - if (constraint.getRegExp()!=null && - constraint.getRegExp().length() > 0 && - !constraint.getRegExp().equals(regexp)) { + if (constraint.getRegExp() != null && constraint.getRegExp().length() > 0 && !constraint.getRegExp().equals(regexp)) { throw new MalformedPatternException(SSRBundle.message("error.two.different.type.constraints")); - } else { - try { - Pattern.compile(regexp); - } catch (PatternSyntaxException e) { - throw new MalformedPatternException(SSRBundle.message("invalid.regular.expression")); - } + } + else { + checkRegex(regexp); constraint.setRegExp(regexp); } @@ -326,146 +305,162 @@ class StringToConstraintsTransformer { } private static void parseCondition(MatchVariableConstraint constraint, String condition) { - if (condition.isEmpty()) throw new MalformedPatternException(SSRBundle.message("error.expected.condition", "[")); - final List tokens = StringUtil.split(condition, "&&", true, false); - - for (String token : tokens) { - token = token.trim(); - if (token.isEmpty()) throw new MalformedPatternException(SSRBundle.message("error.expected.condition", "&&")); - boolean hasNot = false; - boolean consumed = false; - - if (StringUtil.startsWithChar(token, '!')) { - token = token.substring(1); - if (token.isEmpty()) throw new MalformedPatternException(SSRBundle.message("error.expected.condition", "!")); - hasNot = true; - } - - Matcher m = p.matcher(token); - - if (m.matches()) { - String option = m.group(1); - - if (option.equalsIgnoreCase(REF)) { - String name = m.group(2); - - constraint.setReference(true); - constraint.setInvertReference(hasNot); - constraint.setNameOfReferenceVar(name); - consumed = true; - } - } else { - m = p2.matcher(token); - - if (m.matches()) { - String option = m.group(1); - - if (option.equalsIgnoreCase(READ)) { - constraint.setReadAccess(true); - constraint.setInvertReadAccess(hasNot); - consumed = true; - } else if (option.equalsIgnoreCase(WRITE)) { - constraint.setWriteAccess(true); - constraint.setInvertWriteAccess(hasNot); - consumed = true; - } - } else { - m = p3.matcher(token); - - if (m.matches()) { - String option = m.group(1); - - if (option.equalsIgnoreCase(REGEX) || option.equalsIgnoreCase(REGEXW)) { - String typePattern = getSingleParameter(m, SSRBundle.message("reg.exp.should.be.delimited.with.spaces.error.message")); - if (typePattern.isEmpty()) throw new MalformedPatternException(SSRBundle.message("no.reg.exp.specified.error.message")); - - if (StringUtil.startsWithChar(typePattern, '*')) { - typePattern = typePattern.substring(1); - constraint.setWithinHierarchy(true); - } - try { - Pattern.compile(typePattern); - } catch (PatternSyntaxException e) { - throw new MalformedPatternException(SSRBundle.message("invalid.regular.expression")); - } - constraint.setRegExp( typePattern ); - constraint.setInvertRegExp( hasNot ); - consumed = true; - if (option.equalsIgnoreCase(REGEXW)) { - constraint.setWholeWordsOnly(true); - } - } else if (option.equalsIgnoreCase(EXPRTYPE)) { - String exprTypePattern = getSingleParameter(m, SSRBundle.message( - "reg.exp.in.expr.type.should.be.delimited.with.spaces.error.message")); - - if (StringUtil.startsWithChar(exprTypePattern, '*')) { - exprTypePattern = exprTypePattern.substring(1); - constraint.setExprTypeWithinHierarchy(true); - } - try { - Pattern.compile(exprTypePattern); - } catch (PatternSyntaxException e) { - throw new MalformedPatternException(SSRBundle.message("invalid.regular.expression")); - } - constraint.setNameOfExprType( exprTypePattern ); - constraint.setInvertExprType( hasNot ); - consumed = true; - } else if (option.equalsIgnoreCase(FORMAL)) { - String exprTypePattern = getSingleParameter(m, SSRBundle.message( - "reg.exp.in.formal.arg.type.should.be.delimited.with.spaces.error.message")); - - if (StringUtil.startsWithChar(exprTypePattern, '*')) { - exprTypePattern = exprTypePattern.substring(1); - constraint.setFormalArgTypeWithinHierarchy(true); - } - try { - Pattern.compile(exprTypePattern); - } catch (PatternSyntaxException e) { - throw new MalformedPatternException(SSRBundle.message("invalid.regular.expression")); - } - constraint.setNameOfFormalArgType( exprTypePattern ); - constraint.setInvertFormalType( hasNot ); - consumed = true; - } else if (option.equalsIgnoreCase(SCRIPT)) { - String script = getSingleParameter(m, SSRBundle.message("script.should.be.delimited.with.spaces.error.message")); - - constraint.setScriptCodeConstraint( script ); - consumed = true; - } else if (option.equalsIgnoreCase(CONTAINS)) { - if (hasNot) constraint.setInvertContainsConstraint(true); - String script = getSingleParameter(m, SSRBundle.message("script.should.be.delimited.with.spaces.error.message")); - - constraint.setContainsConstraint(script ); - consumed = true; - } else if (option.equalsIgnoreCase(WITHIN)) { - if (!Configuration.CONTEXT_VAR_NAME.equals(constraint.getName())) { - throw new MalformedPatternException("Within constraint is only applicable to Complete Match"); - } - if (hasNot) constraint.setInvertWithinConstraint(true); - String script = getSingleParameter(m, SSRBundle.message("script.should.be.delimited.with.spaces.error.message")); - - constraint.setWithinConstraint(script); - consumed = true; + final int length = condition.length(); + final StringBuilder text = new StringBuilder(); + boolean invert = false; + boolean optionExpected = true; + for (int i = 0; i < length; i++) { + char c = condition.charAt(i); + if (Character.isWhitespace(c)) { + if (text.length() == 0) continue; + handleOption(constraint, text.toString(), "", invert); + optionExpected = false; + } + else if (c == '(') { + if (text.length() == 0) throw new MalformedPatternException(SSRBundle.message("error.expected.condition.name")); + final String option = text.toString(); + text.setLength(0); + int spaces = 0; // balance spaces surrounding content between parentheses + while (++i < length && condition.charAt(i) == ' ') spaces++; + i--; + boolean quoted = false; + boolean closed = false; + while (++i < length) { + c = condition.charAt(i); + if (condition.charAt(i - 1) != '\\') { + if (c == '"') quoted = !quoted; + else if (c == ')' && !quoted) { + int j = 1; + while (j <= spaces && condition.charAt(i - j) == ' ') j++; + if (j - 1 == spaces) { + closed = true; + break; } } } + text.append(c); } - - if (!consumed) { - throw new UnsupportedPatternException( - SSRBundle.message("option.is.not.recognized.error.message", token) - ); + if (quoted) throw new MalformedPatternException(SSRBundle.message("error.expected.value", "\"")); + if (!closed) throw new MalformedPatternException(SSRBundle.message("error.expected.value", + StringUtil.repeatSymbol(' ', spaces) + ")")); + handleOption(constraint, option, text.toString(), invert); + text.setLength(0); + invert = false; + optionExpected = false; + } + else if (c == '&') { + if (text.length() != 0) { + handleOption(constraint, text.toString(), "", invert); + optionExpected = false; } + if (++i == length || condition.charAt(i) != '&' || optionExpected) + throw new MalformedPatternException(SSRBundle.message("error.unexpected.value", "&")); + text.setLength(0); + invert = false; + optionExpected = true; + } + else if (!optionExpected) { + throw new MalformedPatternException(SSRBundle.message("error.expected.value", "&&")); + } + else if (c == '!') { + if (text.length() != 0) throw new MalformedPatternException(SSRBundle.message("error.unexpected.value", "!")); + invert = !invert; + } + else { + text.append(c); } } + if (text.length() != 0) { + handleOption(constraint, text.toString(), "", invert); + } + else if (invert) throw new MalformedPatternException(SSRBundle.message("error.expected.condition", "!")); + else if (optionExpected) throw new MalformedPatternException(SSRBundle.message("error.expected.condition", "&&")); + } - private static String getSingleParameter(Matcher m, String errorMessage) { - final String value = m.group(2); - if (value.isEmpty()) return value; + private static void handleOption(@NotNull MatchVariableConstraint constraint, @NotNull String option, @NotNull String argument, + boolean invert) { + argument = argument.trim(); + if (option.equalsIgnoreCase(REF)) { + constraint.setReference(true); + constraint.setInvertReference(invert); + if (argument.length() == 0 || argument.charAt(0) != '\'') + throw new MalformedPatternException(SSRBundle.message("error.reference.variable.name.expected", option)); + constraint.setNameOfReferenceVar(argument.substring(1)); + } + else if (option.equalsIgnoreCase(READ)) { + if (argument.length() != 0) throw new MalformedPatternException(SSRBundle.message("error.no.argument.expected", option)); + constraint.setReadAccess(true); + constraint.setInvertReadAccess(invert); + } + else if (option.equalsIgnoreCase(WRITE)) { + if (argument.length() != 0) throw new MalformedPatternException(SSRBundle.message("error.no.argument.expected", option)); + constraint.setWriteAccess(true); + constraint.setInvertWriteAccess(invert); + } + else if (option.equalsIgnoreCase(REGEX) || option.equalsIgnoreCase(REGEXW)) { + if (argument.length() == 0) + throw new MalformedPatternException(SSRBundle.message("error.regular.expression.argument.expected", option)); + if (argument.charAt(0) == '*') { + argument = argument.substring(1); + constraint.setWithinHierarchy(true); + } + checkRegex(argument); + constraint.setRegExp(argument); + constraint.setInvertRegExp(invert); + if (option.equalsIgnoreCase(REGEXW)) { + constraint.setWholeWordsOnly(true); + } + } + else if (option.equalsIgnoreCase(EXPRTYPE)) { + if (argument.length() == 0) + throw new MalformedPatternException(SSRBundle.message("error.regular.expression.argument.expected", option)); + if (argument.charAt(0) == '*') { + argument = argument.substring(1); + constraint.setExprTypeWithinHierarchy(true); + } + checkRegex(argument); + constraint.setNameOfExprType(argument); + constraint.setInvertExprType(invert); + } + else if (option.equalsIgnoreCase(FORMAL)) { + if (argument.length() == 0) + throw new MalformedPatternException(SSRBundle.message("error.regular.expression.argument.expected", option)); + if (argument.charAt(0) == '*') { + argument = argument.substring(1); + constraint.setFormalArgTypeWithinHierarchy(true); + } + checkRegex(argument); + constraint.setNameOfFormalArgType(argument); + constraint.setInvertFormalType(invert); + } + else if (option.equalsIgnoreCase(SCRIPT)) { + if (argument.length() == 0) throw new MalformedPatternException(SSRBundle.message("error.script.argument.expected", option)); + if (invert) throw new MalformedPatternException(SSRBundle.message("error.cannot.invert", option)); + constraint.setScriptCodeConstraint(argument); + } + else if (option.equalsIgnoreCase(CONTAINS)) { + if (argument.length() == 0) throw new MalformedPatternException(SSRBundle.message("error.pattern.argument.expected", option)); + constraint.setContainsConstraint(argument); + constraint.setInvertContainsConstraint(invert); + } + else if (option.equalsIgnoreCase(WITHIN)) { + if (!Configuration.CONTEXT_VAR_NAME.equals(constraint.getName())) + throw new MalformedPatternException(SSRBundle.message("error.only.applicable.to.complete.match", option)); + if (argument.length() == 0) throw new MalformedPatternException(SSRBundle.message("error.pattern.argument.expected", option)); + constraint.setWithinConstraint(argument); + constraint.setInvertWithinConstraint(invert); + } + else { + throw new UnsupportedPatternException(SSRBundle.message("option.is.not.recognized.error.message", option)); + } + } - if (value.charAt(0)!=' ' || value.charAt(value.length()-1)!=' ') { - throw new MalformedPatternException(errorMessage); + private static void checkRegex(@NotNull String regex) { + try { + Pattern.compile(regex); + } + catch (PatternSyntaxException ignored) { + throw new MalformedPatternException(SSRBundle.message("invalid.regular.expression", regex)); } - return value.trim(); } } diff --git a/platform/structuralsearch/source/messages/SSRBundle.properties b/platform/structuralsearch/source/messages/SSRBundle.properties index 2ccdf549dd28..13fa154b93ab 100644 --- a/platform/structuralsearch/source/messages/SSRBundle.properties +++ b/platform/structuralsearch/source/messages/SSRBundle.properties @@ -152,7 +152,7 @@ predefined.configuration.lambdas=lambdas predefined.configuration.method.references=method references # edit variable constraint dialog options -invalid.regular.expression=Invalid regular expression +invalid.regular.expression=Invalid regular expression ''{0}'' invalid.occurence.count=Invalid occurrence count editvarcontraints.this.variable.is.target.of.the.search=This variable is target of the search editvarcontraints.unlimited=Unlimited @@ -202,23 +202,29 @@ var.constraints.script.constraints.border=Script constraints var.constraints.expression.constraints.border=Expression constraints var.constraints.text.constraints.border=Text constraints different.strategies.for.top.level.nodes.error.message=Different strategies for top level nodes -option.is.not.recognized.error.message={0} condition is not recognized -reg.exp.should.be.delimited.with.spaces.error.message=Reg exp should be delimited with spaces -reg.exp.in.expr.type.should.be.delimited.with.spaces.error.message=Reg exp in expr type should be delimited with spaces -reg.exp.in.formal.arg.type.should.be.delimited.with.spaces.error.message=Reg exp in formal arg type should be delimited with spaces -no.reg.exp.specified.error.message=Missing regular expression -script.should.be.delimited.with.spaces.error.message=Script should be delimited with spaces +option.is.not.recognized.error.message=Constraint ''{0}'' not recognized +error.only.one.target.allowed=Only one target allowed +error.condition.only.on.first.variable.reference=Constraints are only allowed on the first reference of a variable error.two.different.type.constraints=Two different type constraints error.incorrect.regexp.constraint=Incorrect reg exp constraint:{0} for {1} error.expected.character=Character expected after single quote error.overflow=Value overflow error.expected.brace1=Digit, '}' or ',' expected error.expected.brace2=Digit or '}' expected -error.expected.condition=Condition expected after ''{0}'' -error.expected.condition.or.bracket=Condition or ']' expected -error.expected.end.quote='"' expected +error.expected.condition=Constraint expected after ''{0}'' +error.expected.condition.or.bracket=Constraint or ']' expected +error.expected.condition.name=Constraint name missing +error.expected.value=''{0}'' expected +error.unexpected.value=Unexpected ''{0}'' invalid.modifier.type=Invalid modifier type {0} +error.reference.variable.name.expected=Name of reference variable argument expected on ''{0}'' option +error.no.argument.expected=No argument expected on ''{0}'' option +error.regular.expression.argument.expected=Regular expression argument expected on ''{0}'' option +error.pattern.argument.expected=Pattern argument expected on ''{0}'' option +error.script.argument.expected=Script argument expected on ''{0}'' option +error.cannot.invert=Cannot invert ''{0}'' option +error.only.applicable.to.complete.match=Constraint ''{0}'' is only applicable to Complete Match SSRInspection.replace.with=Replace with ''{0}'' SSRInspection.family.name=Replace Structurally diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java index f999c01a579f..a67bfcdffa19 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/StructuralSearchTest.java @@ -552,20 +552,12 @@ public class StructuralSearchTest extends StructuralSearchTestCase { String s9 = "int a[] = new int[] { 1,2,3,4};\n" + "int b[] = { 2,3,4,5 };\n" + "Object[] c = new Object[] { \"\", null};"; - String s10 = "new '_ []{ '_* }"; - String s10_2 = "new int []{ '_* }"; - assertEquals( - "Find array instatiation", - 3, - findMatchesCount(s9,s10) - ); - - assertEquals( - "Find array instatiation, 2", - 2, - findMatchesCount(s9,s10_2) - ); + assertEquals("Find array instantiation 1", 2, findMatchesCount(s9, "new '_ []{ '_* }")); + assertEquals("Find array instantiation 2", 2, findMatchesCount(s9, "new int []{ '_* }")); + assertEquals("Find array instantiation 3", 2, findMatchesCount(s9, "new 'a?:int [] { '_* }")); + assertEquals("Find array instantiation 4", 3, findMatchesCount(s9, "new '_? []{ '_* }")); + assertEquals("Find array instantiation 5", 1, findMatchesCount(s9, "new Object[] { '_* }")); } public void testLiteral() { diff --git a/platform/structuralsearch/testSource/com/intellij/structuralsearch/impl/matcher/compiler/StringToConstraintsTransformerTest.java b/platform/structuralsearch/testSource/com/intellij/structuralsearch/impl/matcher/compiler/StringToConstraintsTransformerTest.java index 9b58cc87b1ad..bfdadf49a45e 100644 --- a/platform/structuralsearch/testSource/com/intellij/structuralsearch/impl/matcher/compiler/StringToConstraintsTransformerTest.java +++ b/platform/structuralsearch/testSource/com/intellij/structuralsearch/impl/matcher/compiler/StringToConstraintsTransformerTest.java @@ -9,6 +9,8 @@ import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; /** * @author Bas Leijdekkers @@ -101,7 +103,7 @@ public class StringToConstraintsTransformerTest { test("'a:[aap()]"); } - @Test(expected = UnsupportedPatternException.class) + @Test(expected = MalformedPatternException.class) public void testIncompleteCondition() { test("'a:[regex(]"); } @@ -151,11 +153,22 @@ public class StringToConstraintsTransformerTest { } @Test - public void testScriptEscaping() { - test("[within( \"if ('_a:[regex( .*e.* )\\]) { '_st*; }\" )]'_type 'a = '_b;"); + public void testNestedPatterns() { + test("[within( \"if ('_a:[regex( .*e.* )]) { '_st*; }\" )]'_type 'a = '_b;"); assertEquals("$type$ $a$ = $b$;", myOptions.getSearchPattern()); final MatchVariableConstraint constraint = myOptions.getVariableConstraint(Configuration.CONTEXT_VAR_NAME); assertEquals("\"if ('_a:[regex( .*e.* )]) { '_st*; }\"", constraint.getWithinConstraint()); + + test("[!within( \"<'_tag:[regex( ul|ol )] />\" )]
      2. "); + assertEquals("
      3. ", myOptions.getSearchPattern()); + final MatchVariableConstraint constraint2 = myOptions.getVariableConstraint(Configuration.CONTEXT_VAR_NAME); + assertEquals("\"<'_tag:[regex( ul|ol )] />\"", constraint2.getWithinConstraint()); + assertTrue(constraint2.isInvertWithinConstraint()); + + test("[within( \"if ('_a:[regex( \".*\" )]) { '_st*; }\" )]'_type 'a = '_b;"); + assertEquals("$type$ $a$ = $b$;", myOptions.getSearchPattern()); + final MatchVariableConstraint constraint3 = myOptions.getVariableConstraint(Configuration.CONTEXT_VAR_NAME); + assertEquals("\"if ('_a:[regex( \".*\" )]) { '_st*; }\"", constraint3.getWithinConstraint()); } @Test @@ -186,6 +199,46 @@ public class StringToConstraintsTransformerTest { assertEquals("'\\u0123'$a$", myOptions.getSearchPattern()); } + @Test + public void testComplexRegexes() { + test("'_t:[regex( *Object\\[\\] ) ] '_t2"); + assertEquals("$t$ $t2$", myOptions.getSearchPattern()); + final MatchVariableConstraint constraint = myOptions.getVariableConstraint("t"); + assertTrue(constraint.isWithinHierarchy()); + assertEquals("Object\\[\\]", constraint.getRegExp()); + + test("// 'Comment:[regex( .*(?:comment).* )]"); + assertEquals("// $Comment$", myOptions.getSearchPattern()); + final MatchVariableConstraint constraint1 = myOptions.getVariableConstraint("Comment"); + assertEquals(".*(?:comment).*", constraint1.getRegExp()); + } + + @Test + public void testInvert() { + test("'a:[!read&&write]"); + assertEquals("$a$", myOptions.getSearchPattern()); + final MatchVariableConstraint constraint = myOptions.getVariableConstraint("a"); + assertTrue(constraint.isReadAccess()); + assertTrue(constraint.isInvertReadAccess()); + assertTrue(constraint.isWriteAccess()); + assertFalse(constraint.isInvertWriteAccess()); + } + + @Test(expected = MalformedPatternException.class) + public void testAmpersandsExpected() { + test("'a:[read write]"); + } + + @Test(expected = MalformedPatternException.class) + public void testUnexpectedAmpersands() { + test("'a:[&&read]"); + } + + @Test(expected = MalformedPatternException.class) + public void testUnbalancedSpacesSurroundingContent() { + test("'a:[regex( .* ) ]"); + } + private void test(String pattern) { myOptions.setSearchPattern(pattern); StringToConstraintsTransformer.transformOldPattern(myOptions); diff --git a/platform/testFramework/src/com/intellij/mock/MockVirtualFileSystem.java b/platform/testFramework/src/com/intellij/mock/MockVirtualFileSystem.java index 9854cea82835..848fda627e29 100644 --- a/platform/testFramework/src/com/intellij/mock/MockVirtualFileSystem.java +++ b/platform/testFramework/src/com/intellij/mock/MockVirtualFileSystem.java @@ -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); diff --git a/platform/util/src/com/intellij/openapi/util/JDOMExternalizerUtil.java b/platform/util/src/com/intellij/openapi/util/JDOMExternalizerUtil.java index 9a9fc7b2652e..99c1147980d4 100644 --- a/platform/util/src/com/intellij/openapi/util/JDOMExternalizerUtil.java +++ b/platform/util/src/com/intellij/openapi/util/JDOMExternalizerUtil.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2013 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,6 +21,7 @@ import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collection; import java.util.Collections; import java.util.List; @@ -113,6 +114,7 @@ public class JDOMExternalizerUtil { return values; } + @SuppressWarnings("Duplicates") public static void addChildrenWithValueAttribute(@NotNull Element parent, @NotNull String childTagName, @NotNull List attrValues) { @@ -124,4 +126,17 @@ public class JDOMExternalizerUtil { } } } + + @SuppressWarnings({"deprecation", "Duplicates"}) + public static void addChildren(@NotNull Element parent, + @NotNull String childElementName, + @NotNull Collection children) throws WriteExternalException { + for (JDOMExternalizable child : children) { + if (child != null) { + Element element = new Element(childElementName); + child.writeExternal(element); + parent.addContent(element); + } + } + } } diff --git a/platform/util/src/com/intellij/openapi/util/io/FileAttributes.java b/platform/util/src/com/intellij/openapi/util/io/FileAttributes.java index f3b417373119..543377a2f564 100644 --- a/platform/util/src/com/intellij/openapi/util/io/FileAttributes.java +++ b/platform/util/src/com/intellij/openapi/util/io/FileAttributes.java @@ -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 } diff --git a/platform/util/src/com/intellij/util/keyFMap/ArrayBackedFMap.java b/platform/util/src/com/intellij/util/keyFMap/ArrayBackedFMap.java index 000f225bc1f2..05717393eee8 100644 --- a/platform/util/src/com/intellij/util/keyFMap/ArrayBackedFMap.java +++ b/platform/util/src/com/intellij/util/keyFMap/ArrayBackedFMap.java @@ -18,7 +18,7 @@ package com.intellij.util.keyFMap; import com.intellij.openapi.util.Key; import org.jetbrains.annotations.NotNull; -class ArrayBackedFMap implements KeyFMap { +public class ArrayBackedFMap implements KeyFMap { static final int ARRAY_THRESHOLD = 8; private final int[] keys; private final Object[] values; @@ -134,4 +134,12 @@ class ArrayBackedFMap implements KeyFMap { public boolean isEmpty() { return false; } + + public int[] getKeys() { + return keys; + } + + public Object[] getValues() { + return values; + } } diff --git a/platform/util/src/com/intellij/util/keyFMap/PairElementsFMap.java b/platform/util/src/com/intellij/util/keyFMap/PairElementsFMap.java index bb8b8d0ace15..b6e5a21bd58e 100644 --- a/platform/util/src/com/intellij/util/keyFMap/PairElementsFMap.java +++ b/platform/util/src/com/intellij/util/keyFMap/PairElementsFMap.java @@ -18,7 +18,7 @@ package com.intellij.util.keyFMap; import com.intellij.openapi.util.Key; import org.jetbrains.annotations.NotNull; -class PairElementsFMap implements KeyFMap { +public class PairElementsFMap implements KeyFMap { private final Key key1; private final Key key2; private final Object value1; @@ -63,4 +63,20 @@ class PairElementsFMap implements KeyFMap { public boolean isEmpty() { return false; } + + public Key getKey1() { + return key1; + } + + public Key getKey2() { + return key2; + } + + public Object getValue1() { + return value1; + } + + public Object getValue2() { + return value2; + } } diff --git a/platform/util/src/com/intellij/util/xmlb/SkipDefaultValuesSerializationFilters.java b/platform/util/src/com/intellij/util/xmlb/SkipDefaultValuesSerializationFilters.java index 559ad12f8dab..b4c24c6b7b90 100644 --- a/platform/util/src/com/intellij/util/xmlb/SkipDefaultValuesSerializationFilters.java +++ b/platform/util/src/com/intellij/util/xmlb/SkipDefaultValuesSerializationFilters.java @@ -28,6 +28,14 @@ import java.util.Map; public class SkipDefaultValuesSerializationFilters extends SerializationFilterBase { private final Map, Object> myDefaultBeans = new THashMap, Object>(); + public SkipDefaultValuesSerializationFilters() { } + + public SkipDefaultValuesSerializationFilters(Object... defaultBeans) { + for (Object defaultBean : defaultBeans) { + myDefaultBeans.put(defaultBean.getClass(), defaultBean); + } + } + @Override protected boolean accepts(@NotNull Accessor accessor, @NotNull Object bean, @Nullable Object beanValue) { Object defValue = accessor.read(getDefaultBean(bean)); @@ -43,12 +51,13 @@ public class SkipDefaultValuesSerializationFilters extends SerializationFilterBa Object getDefaultBean(@NotNull Object bean) { Class c = bean.getClass(); Object o = myDefaultBeans.get(c); + if (o == null) { o = ReflectionUtil.newInstance(c); configure(o); - myDefaultBeans.put(c, o); } + return o; } diff --git a/platform/util/src/com/intellij/util/xmlb/SkipEmptySerializationFilter.java b/platform/util/src/com/intellij/util/xmlb/SkipEmptySerializationFilter.java index aec1ab68e74a..a45c3514e0fa 100644 --- a/platform/util/src/com/intellij/util/xmlb/SkipEmptySerializationFilter.java +++ b/platform/util/src/com/intellij/util/xmlb/SkipEmptySerializationFilter.java @@ -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. @@ -35,9 +35,9 @@ public class SkipEmptySerializationFilter extends SerializationFilterBase { } if (Boolean.FALSE.equals(beanValue) || - (beanValue instanceof String && ((String)beanValue).isEmpty()) || + beanValue instanceof String && ((String)beanValue).isEmpty() || beanValue instanceof Collection && ((Collection)beanValue).isEmpty() || - (beanValue instanceof Map && ((Map)beanValue).isEmpty())) { + beanValue instanceof Map && ((Map)beanValue).isEmpty()) { return false; } diff --git a/platform/vcs-api/src/com/intellij/openapi/vcs/vfs/VcsFileSystem.java b/platform/vcs-api/src/com/intellij/openapi/vcs/vfs/VcsFileSystem.java index 8cea93b349c3..244dc87f58b7 100644 --- a/platform/vcs-api/src/com/intellij/openapi/vcs/vfs/VcsFileSystem.java +++ b/platform/vcs-api/src/com/intellij/openapi/vcs/vfs/VcsFileSystem.java @@ -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); - } } diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java index b71c72be9fb2..cf0cc2d3a7ff 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/XDebugSessionImpl.java @@ -275,6 +275,7 @@ public class XDebugSessionImpl implements XDebugSession { @Override public void processTerminated(final ProcessEvent event) { stopImpl(); + myDebugProcess.getProcessHandler().removeProcessListener(this); } }); //todo[nik] make 'createConsole()' method return ConsoleView diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml index b0f9978b7729..afd0b80d0cc4 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/META-INF/InspectionGadgets.xml @@ -2149,8 +2149,8 @@ - - - - - - - 400; private final int m_foo2 = -(-(400)); private static final List s_set = new ArrayList(400); + private static final Dimension PREFERRED_SIZE = new Dimension(600, 400); public static void main(String[] args) { @@ -18,6 +21,10 @@ public class MagicNumber set.toString(); } + public Dimension getScreenSize() { + return new Dimension(2880, 1800); + } + public boolean equals(final Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; @@ -31,6 +38,9 @@ public class MagicNumber } public int hashCode() { + new Object() { + private int i = 987; + }; int result; result = m_foo; result = 29 * result + m_foo2; @@ -38,7 +48,7 @@ public class MagicNumber } void foo() { - final int value = 101 * 55; + final int value = 101 * 55; } ByteArrayOutputStream out = new ByteArrayOutputStream(756); @@ -49,4 +59,34 @@ public class MagicNumber } @interface Size { int max(); +} +enum Planet { + MERCURY (3.303e+23, 2.4397e6), + VENUS (4.869e+24, 6.0518e6), + EARTH (5.976e+24, 6.37814e6), + MARS (6.421e+23, 3.3972e6), + JUPITER (1.9e+27, 7.1492e7), + SATURN (5.688e+26, 6.0268e7), + URANUS (8.686e+25, 2.5559e7), + NEPTUNE (1.024e+26, 2.4746e7), + PLUTO (1.27e+22, 1.137e6); + + private final double mass; // in kilograms + private final double radius; // in meters + Planet(double mass, double radius) { + this.mass = mass; + this.radius = radius; + } + public double mass() { return mass; } + public double radius() { return radius; } + + // universal gravitational constant (m3 kg-1 s-2) + public static final double G = 6.67300E-11; + + public double surfaceGravity() { + return G * mass / (radius * radius); + } + public double surfaceWeight(double otherMass) { + return otherMass * surfaceGravity(); + } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/unnecessary_local_vars/C.java b/plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/unnecessary_local_vars/C.java index c316742bb3e9..b188ba7ea2ac 100644 --- a/plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/unnecessary_local_vars/C.java +++ b/plugins/InspectionGadgets/test/com/siyeh/igtest/dataflow/unnecessary_local_vars/C.java @@ -125,5 +125,18 @@ class C { } } } - } + } + + void nameShadow(final String name) { + final String child = name; + class A { + void foo(String s){} + } + + A a = new A() { + void foo(String name) { + System.out.println(child); + } + }; + } } \ No newline at end of file diff --git a/plugins/eclipse/common-eclipse-util/src/AbstractEclipseClasspathReader.java b/plugins/eclipse/common-eclipse-util/src/AbstractEclipseClasspathReader.java index 540318670333..161463d697c5 100644 --- a/plugins/eclipse/common-eclipse-util/src/AbstractEclipseClasspathReader.java +++ b/plugins/eclipse/common-eclipse-util/src/AbstractEclipseClasspathReader.java @@ -94,7 +94,6 @@ public abstract class AbstractEclipseClasspathReader { throw new ConversionException("Missing classpathentry/@kind"); } - String path = element.getAttributeValue(EclipseXml.PATH_ATTR); if (path == null) { //noinspection SpellCheckingInspection @@ -113,7 +112,7 @@ public abstract class AbstractEclipseClasspathReader { String srcUrl = pathToUrl(myRootPath + "/" + path); boolean isTestFolder; try { - isTestFolder = testPattern != null && testPattern.length() > 0 && path.matches(testPattern); + isTestFolder = !StringUtil.isEmpty(testPattern) && path.matches(testPattern); } catch (PatternSyntaxException e) { isTestFolder = false; @@ -136,7 +135,6 @@ public abstract class AbstractEclipseClasspathReader { } } } - else if (kind.equals(EclipseXml.OUTPUT_KIND)) { String output = myRootPath + "/" + path; String linked = expandLinkedResourcesPath(macroMap, path); @@ -148,10 +146,7 @@ public abstract class AbstractEclipseClasspathReader { } setupOutput(rootModel, output); } - else if (kind.equals(EclipseXml.LIB_KIND)) { - final String libName = getPresentableName(path, libs); - String linked = expandLinkedResourcesPath(macroMap, path); String url; if (linked != null) { @@ -183,7 +178,7 @@ public abstract class AbstractEclipseClasspathReader { } } - addModuleLibrary(rootModel, element, exported, libName, url, srcUrl, macroMap); + addModuleLibrary(rootModel, element, exported, getPresentableName(path, libs), url, srcUrl, macroMap); } else if (kind.equals(EclipseXml.VAR_KIND)) { int slash = path.indexOf("/"); @@ -258,9 +253,13 @@ public abstract class AbstractEclipseClasspathReader { @NotNull protected static String getPresentableName(@NotNull String path, Set names) { - final String pathComponent = getLastPathComponent(path); - if (pathComponent != null && names != null && !names.add(pathComponent)) return path; - return pathComponent != null ? pathComponent : path; + String pathComponent = getLastPathComponent(path); + if (pathComponent != null && names != null && !names.add(pathComponent)) { + return path; + } + else { + return pathComponent == null ? path : pathComponent; + } } @Nullable diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/config/EclipseModuleManagerImpl.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/config/EclipseModuleManagerImpl.java index 515c9f61c217..633592095931 100644 --- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/config/EclipseModuleManagerImpl.java +++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/config/EclipseModuleManagerImpl.java @@ -16,10 +16,7 @@ package org.jetbrains.idea.eclipse.config; -import com.intellij.openapi.components.PersistentStateComponent; -import com.intellij.openapi.components.State; -import com.intellij.openapi.components.Storage; -import com.intellij.openapi.components.StoragePathMacros; +import com.intellij.openapi.components.*; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleServiceManager; import com.intellij.openapi.roots.impl.storage.ClassPathStorageUtil; @@ -41,7 +38,7 @@ import java.util.Set; name = "EclipseModuleManager", storages = @Storage(file = StoragePathMacros.MODULE_FILE) ) -public class EclipseModuleManagerImpl implements EclipseModuleManager, PersistentStateComponent { +public class EclipseModuleManagerImpl implements EclipseModuleManager, PersistentStateComponent, StateStorageChooserEx { @NonNls private static final String VALUE_ATTR = "value"; @NonNls private static final String VARELEMENT = "varelement"; @NonNls private static final String VAR_ATTRIBUTE = "var"; @@ -180,13 +177,23 @@ public class EclipseModuleManagerImpl implements EclipseModuleManager, Persisten return myEclipseUrls.contains(url); } + @NotNull @Override - public Element getState() { - if (isEclipseStorage(myModule) || - myEclipseUrls.isEmpty() && myEclipseVariablePaths.isEmpty() && !myForceConfigureJDK && myUnknownCons.isEmpty()) { - return null; + public Resolution getResolution(@NotNull Storage storage, @NotNull StateStorageOperation operation) { + if (operation == StateStorageOperation.READ) { + return Resolution.DO; } + if (isEclipseStorage(myModule) || (myEclipseUrls.isEmpty() && myEclipseVariablePaths.isEmpty() && !myForceConfigureJDK && myUnknownCons.isEmpty())) { + return Resolution.CLEAR; + } + else { + return Resolution.DO; + } + } + + @Override + public Element getState() { Element root = new Element("EclipseModuleSettings"); for (String eclipseUrl : myEclipseUrls) { diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/EclipseClasspathWriter.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/EclipseClasspathWriter.java index d76a7c9b3eb0..4b65a21d0fb0 100644 --- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/EclipseClasspathWriter.java +++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/EclipseClasspathWriter.java @@ -252,7 +252,7 @@ public class EclipseClasspathWriter { if (path != null) { orderEntry.setAttribute(EclipseXml.PATH_ATTR, path); } - if (index == -1) { + if (index == -1 || index >= classpathRoot.getContentSize()) { classpathRoot.addContent(orderEntry); } else { diff --git a/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/IdeaSpecificSettings.java b/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/IdeaSpecificSettings.java index bf2389a1b45d..87cf158924e6 100644 --- a/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/IdeaSpecificSettings.java +++ b/plugins/eclipse/src/org/jetbrains/idea/eclipse/conversion/IdeaSpecificSettings.java @@ -42,6 +42,7 @@ import org.jdom.Element; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.eclipse.AbstractEclipseClasspathReader; import org.jetbrains.idea.eclipse.IdeaXml; import org.jetbrains.idea.eclipse.config.EclipseModuleManagerImpl; @@ -77,23 +78,22 @@ public class IdeaSpecificSettings extends AbstractIdeaSpecificSettings 0 ? srcUrlsFromClasspath[0] : null; - for (Object r : libElement.getChildren(SRCROOT_ATTR)) { - final String url = ((Element)r).getAttributeValue("url"); - final String bindAttr = ((Element)r).getAttributeValue(SRCROOT_BIND_ATTR); + for (Element r : libElement.getChildren(SRCROOT_ATTR)) { + final String url = r.getAttributeValue("url"); + final String bindAttr = r.getAttributeValue(SRCROOT_BIND_ATTR); boolean notBind = bindAttr != null && !Boolean.parseBoolean(bindAttr); if (notBind) { modifiableModel.addRoot(url, OrderRootType.SOURCES); @@ -205,8 +206,8 @@ public class IdeaSpecificSettings extends AbstractIdeaSpecificSettings 0) { + VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(urls[0]); + file = JarFileSystem.getInstance().getVirtualFileForJar(file); + libraryName = file != null ? file.getName() : null; + } + if (libraryName == null) { + libraryName = libraryEntry.getPresentableName(); + } + } + + element.setAttribute("name", libraryName); DependencyScope scope = libraryEntry.getScope(); element.setAttribute("scope", scope.name()); if (libraryEntry.isModuleLevel()) { @@ -408,8 +422,8 @@ public class IdeaSpecificSettings extends AbstractIdeaSpecificSettings urls = new ArrayList(Arrays.asList(modifiableModel.getUrls(orderRootType))); - for (Object r : libElement.getChildren(relativeModuleName)) { - final String root = PathMacroManager.getInstance(project).expandPath(((Element)r).getAttributeValue(PROJECT_RELATED)); + for (Element r : libElement.getChildren(relativeModuleName)) { + final String root = PathMacroManager.getInstance(project).expandPath(r.getAttributeValue(PROJECT_RELATED)); for (Iterator iterator = urls.iterator(); iterator.hasNext();) { final String url = iterator.next(); if (areUrlsPointTheSame(root, url)) { @@ -424,18 +438,23 @@ public class IdeaSpecificSettings extends AbstractIdeaSpecificSettings module2StorageRoot = new LinkedHashMap(); for (Module module : dialog.getSelectedModules()) { - ModuleRootModel model = ModuleRootManager.getInstance(module); - VirtualFile[] contentRoots = model.getContentRoots(); + VirtualFile[] contentRoots = ModuleRootManager.getInstance(module).getContentRoots(); String storageRoot = contentRoots.length == 1 ? contentRoots[0].getPath() : ClasspathStorage.getStorageRootFromOptions(module); + module2StorageRoot.put(module, storageRoot); + try { + DotProjectFileHelper.saveDotProjectFile(module, storageRoot); + } + catch (Exception e1) { + LOG.error(e1); + } + } + + for (Module module : module2StorageRoot.keySet()) { + ModuleRootModel model = ModuleRootManager.getInstance(module); + String storageRoot = module2StorageRoot.get(module); try { Element classpathElement = new EclipseClasspathWriter().writeClasspath(null, model); File classpathFile = new File(storageRoot, EclipseXml.CLASSPATH_FILE); @@ -139,7 +152,6 @@ public class ExportEclipseProjectsAction extends AnAction implements DumbAware { EclipseJDOMUtil.output(ideaSpecific, emlFile, project); } - DotProjectFileHelper.saveDotProjectFile(module, storageRoot); } catch (Exception e1) { LOG.error(e1); diff --git a/plugins/groovy/groovy-psi/gen/icons/JetgroovyIcons.java b/plugins/groovy/groovy-psi/gen/icons/JetgroovyIcons.java index 622af34de0fb..845b18e4f2b1 100644 --- a/plugins/groovy/groovy-psi/gen/icons/JetgroovyIcons.java +++ b/plugins/groovy/groovy-psi/gen/icons/JetgroovyIcons.java @@ -52,6 +52,7 @@ public class JetgroovyIcons { public static final Icon Groovy_13x13 = load("/icons/groovy/groovy_13x13.png"); // 13x13 public static final Icon Groovy_16x16 = load("/icons/groovy/groovy_16x16.png"); // 16x16 public static final Icon Groovy_32x32 = load("/icons/groovy/groovy_32x32.png"); // 32x32 + public static final Icon Groovy_outsideSources = load("/icons/groovy/groovy_outsideSources.png"); // 16x16 public static final Icon GroovyDoc = load("/icons/groovy/GroovyDoc.png"); // 16x16 public static final Icon GroovyModule = load("/icons/groovy/groovyModule.png"); // 24x24 public static final Icon Interface = load("/icons/groovy/interface.png"); // 16x16 diff --git a/plugins/groovy/groovy-psi/resources/icons/groovy/groovy_outsideSources.png b/plugins/groovy/groovy-psi/resources/icons/groovy/groovy_outsideSources.png new file mode 100644 index 000000000000..3addfef6033f Binary files /dev/null and b/plugins/groovy/groovy-psi/resources/icons/groovy/groovy_outsideSources.png differ diff --git a/plugins/groovy/groovy-psi/resources/icons/groovy/groovy_outsideSources@2x.png b/plugins/groovy/groovy-psi/resources/icons/groovy/groovy_outsideSources@2x.png new file mode 100644 index 000000000000..3b4e126f1529 Binary files /dev/null and b/plugins/groovy/groovy-psi/resources/icons/groovy/groovy_outsideSources@2x.png differ diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/GroovyFileIconProvider.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/GroovyFileIconProvider.java new file mode 100644 index 000000000000..081cde4bc45d --- /dev/null +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/GroovyFileIconProvider.java @@ -0,0 +1,64 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.plugins.groovy; + +import com.intellij.ide.FileIconProvider; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Iconable; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiManager; +import com.intellij.psi.impl.ElementBase; +import icons.JetgroovyIcons; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.extensions.GroovyScriptTypeDetector; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; +import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; +import org.jetbrains.plugins.groovy.util.GrFileIndexUtil; + +import javax.swing.*; + +/** + * @author peter + */ +public class GroovyFileIconProvider implements FileIconProvider { + + @Nullable + @Override + public Icon getIcon(@NotNull VirtualFile virtualFile, @Iconable.IconFlags int flags, @Nullable Project project) { + if (project == null || virtualFile.getFileType() != GroovyFileType.GROOVY_FILE_TYPE) return null; + final PsiFile psiFile = PsiManager.getInstance(project).findFile(virtualFile); + if (!(psiFile instanceof GroovyFile)) return null; + final GroovyFile file = (GroovyFile)psiFile; + final Icon icon; + if (GrFileIndexUtil.isGroovySourceFile(file)) { + if (file.isScript()) { + icon = GroovyScriptTypeDetector.getIcon(file); + } + else { + final GrTypeDefinition[] typeDefinitions = file.getTypeDefinitions(); + icon = typeDefinitions.length > 0 + ? typeDefinitions[0].getIcon(flags) + : JetgroovyIcons.Groovy.Groovy_16x16; + } + } + else { + icon = JetgroovyIcons.Groovy.Groovy_outsideSources; + } + return ElementBase.createLayeredIcon(psiFile, icon, ElementBase.transformFlags(psiFile, flags)); + } +} diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/GroovyIconProvider.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/GroovyIconProvider.java deleted file mode 100644 index 1449adf6672a..000000000000 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/GroovyIconProvider.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2000-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package org.jetbrains.plugins.groovy; - -import com.intellij.ide.IconProvider; -import com.intellij.psi.PsiElement; -import icons.JetgroovyIcons; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.plugins.groovy.extensions.GroovyScriptTypeDetector; -import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; -import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinition; - -import javax.swing.*; - -/** - * @author peter - */ -public class GroovyIconProvider extends IconProvider { - - @Override - @Nullable - public Icon getIcon(@NotNull PsiElement element, int flags) { - if (element instanceof GroovyFile) { - GroovyFile file = (GroovyFile)element; - if (!file.isScript()) { - GrTypeDefinition[] typeDefinitions = file.getTypeDefinitions(); - if (typeDefinitions.length > 0) { - return typeDefinitions[0].getIcon(flags); - } - return JetgroovyIcons.Groovy.Groovy_16x16; - } - - return GroovyScriptTypeDetector.getIcon(file); - } - - return null; - } - -} diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/GrReferenceHighlighterFactory.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/GrReferenceHighlighterFactory.java index 457522f66326..ad1011288c9c 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/GrReferenceHighlighterFactory.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/annotator/GrReferenceHighlighterFactory.java @@ -24,6 +24,7 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; +import org.jetbrains.plugins.groovy.util.GrFileIndexUtil; /** * @author Max Medvedev @@ -36,7 +37,7 @@ public class GrReferenceHighlighterFactory extends AbstractProjectComponent impl @Override public TextEditorHighlightingPass createHighlightingPass(@NotNull PsiFile file, @NotNull Editor editor) { - if (!(file instanceof GroovyFileBase)) return null; + if (!GrFileIndexUtil.isGroovySourceFile(file)) return null; return new GrReferenceHighlighter(editor.getDocument(), (GroovyFileBase)file); } } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/dataflow/WritesCounterDFAInstance.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/dataflow/WritesCounterDFAInstance.java index fd9e7bf0ff75..b0c78f385267 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/dataflow/WritesCounterDFAInstance.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/codeInspection/dataflow/WritesCounterDFAInstance.java @@ -36,13 +36,7 @@ public class WritesCounterDFAInstance implements DfaInstance id = (Function)Function.ID; + @Nullable @Contract("null -> null") protected static GrListOrMap getTupleInitializer(@Nullable GrExpression initializer) { @@ -170,17 +171,13 @@ public class GroovyTypeCheckVisitorHelper { @Nullable GrArgumentList argumentList) { if (argumentList == null) return LocalQuickFix.EMPTY_ARRAY; final List args = getExpressionArgumentsOfCall(argumentList); - - if (args == null) { - return LocalQuickFix.EMPTY_ARRAY; - } - + if (args == null) return LocalQuickFix.EMPTY_ARRAY; + + final List> allErrors = new ArrayList>(); final List signatures = GrClosureSignatureUtil.generateSimpleSignatures(signature); - - List> allErrors = new ArrayList>(); for (GrClosureSignature closureSignature : signatures) { - final GrClosureSignatureUtil.MapResultWithError map = GrClosureSignatureUtil.mapSimpleSignatureWithErrors( - closureSignature, argumentTypes, Function.ID, argumentList, 1 + final GrClosureSignatureUtil.MapResultWithError map = GrClosureSignatureUtil.mapSimpleSignatureWithErrors( + closureSignature, argumentTypes, id, argumentList, 1 ); if (map != null) { final List> errors = map.getErrors(); @@ -196,7 +193,6 @@ public class GroovyTypeCheckVisitorHelper { for (Pair error : allErrors) { fixes.add(new ParameterCastFix(error.first, error.second, args.get(error.first))); } - return fixes.toArray(new LocalQuickFix[fixes.size()]); } @@ -269,10 +265,9 @@ public class GroovyTypeCheckVisitorHelper { @Nullable public static List getExpressionArgumentsOfCall(@NotNull GrArgumentList argumentList) { - final GrExpression[] argArray = argumentList.getExpressionArguments(); final ArrayList args = ContainerUtil.newArrayList(); - for (GrExpression arg : argArray) { + for (GroovyPsiElement arg : argumentList.getAllArguments()) { if (arg instanceof GrSpreadArgument) { GrExpression spreaded = ((GrSpreadArgument)arg).getArgument(); if (spreaded instanceof GrListOrMap && !((GrListOrMap)spreaded).isMap()) { @@ -282,8 +277,11 @@ public class GroovyTypeCheckVisitorHelper { return null; } } - else { - args.add(arg); + else if (arg instanceof GrExpression) { + args.add((GrExpression)arg); + } + else if (arg instanceof GrNamedArgument) { + args.add(((GrNamedArgument)arg).getExpression()); } } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/GroovyCoreEnvironment.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/GroovyCoreEnvironment.java index d8b7f97342b1..5157c8eddc82 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/GroovyCoreEnvironment.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/GroovyCoreEnvironment.java @@ -21,7 +21,7 @@ import com.intellij.codeInsight.highlighting.ReadWriteAccessDetector; import com.intellij.codeInspection.unused.ImplicitPropertyUsageProvider; import com.intellij.core.CoreApplicationEnvironment; import com.intellij.core.CoreProjectEnvironment; -import com.intellij.ide.IconProvider; +import com.intellij.ide.FileIconProvider; import com.intellij.javaee.CoreExternalResourceManager; import com.intellij.javaee.ExternalResourceManagerEx; import com.intellij.lang.LanguageAnnotators; @@ -136,7 +136,8 @@ public class GroovyCoreEnvironment { appEnvironment.addExtension(NonCodeMembersContributor.EP_NAME, new DGMMemberContributor()); appEnvironment.addExtension(NonCodeMembersContributor.EP_NAME, new SwingBuilderNonCodeMemberContributor()); - CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), DefaultImportContributor.EP_NAME, DefaultImportContributor.class); + CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), DefaultImportContributor.EP_NAME, + DefaultImportContributor.class); CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), AstTransformContributor.EP_NAME, AstTransformContributor.class); appEnvironment.addExtension(AstTransformContributor.EP_NAME, new AutoCloneContributor()); @@ -146,7 +147,8 @@ public class GroovyCoreEnvironment { appEnvironment.addExtension(AstTransformContributor.EP_NAME, new GrInheritConstructorContributor()); appEnvironment.addExtension(AstTransformContributor.EP_NAME, new LoggingContributor()); - CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), ClosureMissingMethodContributor.EP_NAME, ClosureMissingMethodContributor.class); + CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), ClosureMissingMethodContributor.EP_NAME, + ClosureMissingMethodContributor.class); appEnvironment.addExtension(ClosureMissingMethodContributor.EP_NAME, new PluginXmlClosureMemberContributor()); CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), GrVariableEnhancer.EP_NAME, GrVariableEnhancer.class); @@ -155,7 +157,8 @@ public class GroovyCoreEnvironment { appEnvironment.addExtension(GrVariableEnhancer.EP_NAME, new ClosureParamsEnhancer()); appEnvironment.addExtension(GrVariableEnhancer.EP_NAME, new GppClosureParameterTypeProvider()); - CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), GrReferenceTypeEnhancer.EP_NAME, GrReferenceTypeEnhancer.class); + CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), GrReferenceTypeEnhancer.EP_NAME, + GrReferenceTypeEnhancer.class); appEnvironment.addExtension(GrReferenceTypeEnhancer.EP_NAME, new GroovyMapValueTypeEnhancer()); CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), GrTypeConverter.EP_NAME, GrTypeConverter.class); @@ -172,23 +175,28 @@ public class GroovyCoreEnvironment { appEnvironment.addExtension(GrTypeConverter.EP_NAME, new GrContainerConverter()); appEnvironment.addExtension(GrTypeConverter.EP_NAME, new GppTypeConverter()); - CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), GroovyExpectedTypesContributor.EP_NAME, GroovyExpectedTypesContributor.class); + CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), GroovyExpectedTypesContributor.EP_NAME, + GroovyExpectedTypesContributor.class); appEnvironment.addExtension(GroovyExpectedTypesContributor.EP_NAME, new GppExpectedTypesContributor()); - CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), GroovyScriptTypeDetector.EP_NAME, GroovyScriptTypeDetector.class); + CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), GroovyScriptTypeDetector.EP_NAME, + GroovyScriptTypeDetector.class); CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), GroovyNamedArgumentProvider.EP_NAME, GroovyNamedArgumentProvider.class); appEnvironment.addExtension(GroovyNamedArgumentProvider.EP_NAME, new GroovyConstructorNamedArgumentProvider()); appEnvironment.addExtension(GroovyNamedArgumentProvider.EP_NAME, new GroovyMethodReturnNamedArgumentProvider()); appEnvironment.addExtension(GroovyNamedArgumentProvider.EP_NAME, new GroovySourceCodeNamedArgumentProvider()); appEnvironment.addExtension(GroovyNamedArgumentProvider.EP_NAME, new SwingBuilderNamedArgumentProvider()); - CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), GroovyMapContentProvider.EP_NAME, GroovyMapContentProvider.class); + CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), GroovyMapContentProvider.EP_NAME, + GroovyMapContentProvider.class); appEnvironment.addExtension(GroovyMapContentProvider.EP_NAME, new ConfigSlurperMapContentProvider()); - CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), GroovyUnresolvedHighlightFilter.EP_NAME, GroovyUnresolvedHighlightFilter.class); + CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), GroovyUnresolvedHighlightFilter.EP_NAME, + GroovyUnresolvedHighlightFilter.class); appEnvironment.addExtension(GroovyUnresolvedHighlightFilter.EP_NAME, new GroovyUnresolvedReferenceFilterByFile()); - CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), GroovyUnresolvedHighlightFileFilter.EP_NAME, GroovyUnresolvedHighlightFileFilter.class); + CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), GroovyUnresolvedHighlightFileFilter.EP_NAME, + GroovyUnresolvedHighlightFileFilter.class); CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), GrCallExpressionTypeCalculator.EP_NAME, GrCallExpressionTypeCalculator.class); appEnvironment.addExtension(GrCallExpressionTypeCalculator.EP_NAME, new DefaultCallExpressionTypeCalculator()); appEnvironment.addExtension(GrCallExpressionTypeCalculator.EP_NAME, new GrDescriptorReturnTypeCalculator()); @@ -211,7 +219,8 @@ public class GroovyCoreEnvironment { appEnvironment.addExtension(GdslMembersProvider.EP_NAME, new GdkMethodDslProvider()); appEnvironment.addExtension(GdslMembersProvider.EP_NAME, new GroovyDslDefaultMembers()); - CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), GroovyFrameworkConfigNotification.EP_NAME, GroovyFrameworkConfigNotification.class); + CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), GroovyFrameworkConfigNotification.EP_NAME, + GroovyFrameworkConfigNotification.class); CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), GrMethodMayBeStaticInspectionFilter.EP_NAME, GrMethodMayBeStaticInspectionFilter.class); CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), CustomAnnotationChecker.EP_NAME, CustomAnnotationChecker.class); appEnvironment.addExtension(CustomAnnotationChecker.EP_NAME, new AnnotationCollectorChecker()); @@ -223,24 +232,30 @@ public class GroovyCoreEnvironment { appEnvironment.addExtension(CustomAnnotationChecker.EP_NAME, new NewifyAnnotationChecker()); appEnvironment.addExtension(CustomAnnotationChecker.EP_NAME, new TypeCheckedAnnotationChecker()); - CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), ImplicitPropertyUsageProvider.EP_NAME, ImplicitPropertyUsageProvider.class); + CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), ImplicitPropertyUsageProvider.EP_NAME, + ImplicitPropertyUsageProvider.class); appEnvironment.addExtension(ImplicitPropertyUsageProvider.EP_NAME, new DGMImplicitPropertyUsageProvider()); - CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), ImplicitUsageProvider.EP_NAME, ImplicitUsageProvider.class); + CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), ImplicitUsageProvider.EP_NAME, + ImplicitUsageProvider.class); appEnvironment.addExtension(ImplicitUsageProvider.EP_NAME, new GppImplicitUsageProvider()); appEnvironment.addExtension(ImplicitUsageProvider.EP_NAME, new GrImplicitUsageProvider()); - CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), FileTypeRegistry.FileTypeDetector.EP_NAME, FileTypeRegistry.FileTypeDetector.class); + CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), FileTypeRegistry.FileTypeDetector.EP_NAME, + FileTypeRegistry.FileTypeDetector.class); appEnvironment.addExtension(FileTypeRegistry.FileTypeDetector.EP_NAME, new GroovyHashBangFileTypeDetector()); - CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), ClsCustomNavigationPolicy.EP_NAME, ClsCustomNavigationPolicy.class); + CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), ClsCustomNavigationPolicy.EP_NAME, + ClsCustomNavigationPolicy.class); appEnvironment.addExtension(ClsCustomNavigationPolicy.EP_NAME, new GroovyClsCustomNavigationPolicy()); - CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), PomDeclarationSearcher.EP_NAME, PomDeclarationSearcher.class); + CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), PomDeclarationSearcher.EP_NAME, + PomDeclarationSearcher.class); appEnvironment.addExtension(PomDeclarationSearcher.EP_NAME, new GebContentDeclarationSearcher()); appEnvironment.addExtension(PomDeclarationSearcher.EP_NAME, new SpockPomDeclarationSearcher()); - appEnvironment.addExplicitExtension(LanguageConstantExpressionEvaluator.INSTANCE, GroovyLanguage.INSTANCE, new GroovyConstantExpressionEvaluator()); + appEnvironment.addExplicitExtension(LanguageConstantExpressionEvaluator.INSTANCE, GroovyLanguage.INSTANCE, + new GroovyConstantExpressionEvaluator()); appEnvironment.addExplicitExtension(ExpressionConverter.EP, GroovyLanguage.INSTANCE, new GroovyExpressionConverter()); appEnvironment.addExplicitExtension(LanguageAnnotators.INSTANCE, GroovyLanguage.INSTANCE, new GrAnnotatorImpl()); @@ -282,7 +297,8 @@ public class GroovyCoreEnvironment { appEnvironment.addExtension(StubIndexExtension.EP_NAME, new GrScriptClassNameIndex()); appEnvironment.addExtension(StubIndexExtension.EP_NAME, new GrScriptClassNameIndex()); - CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), FileBasedIndexExtension.EXTENSION_POINT_NAME, FileBasedIndexExtension.class); + CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), FileBasedIndexExtension.EXTENSION_POINT_NAME, + FileBasedIndexExtension.class); appEnvironment.addExtension(FileBasedIndexExtension.EXTENSION_POINT_NAME, new GroovyDslFileIndex()); CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), ReferencesSearch.EP_NAME, QueryExecutor.class); @@ -291,8 +307,8 @@ public class GroovyCoreEnvironment { appEnvironment.addExtension(ReferencesSearch.EP_NAME, new AccessorReferencesSearcher()); appEnvironment.addExtension(ReferencesSearch.EP_NAME, new GroovyTraitFieldSearcher()); - CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), IconProvider.EXTENSION_POINT_NAME, IconProvider.class); - appEnvironment.addExtension(IconProvider.EXTENSION_POINT_NAME, new GroovyIconProvider()); + CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), FileIconProvider.EP_NAME, FileIconProvider.class); + appEnvironment.addExtension(FileIconProvider.EP_NAME, new GroovyFileIconProvider()); CoreApplicationEnvironment.registerExtensionPoint(Extensions.getRootArea(), ResolveScopeProvider.EP_NAME, ResolveScopeProvider.class); appEnvironment.addExtension(ResolveScopeProvider.EP_NAME, new GroovyResolveScopeProvider()); diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrStubElementBase.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrStubElementBase.java index a89fcf50b30c..180759098095 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrStubElementBase.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GrStubElementBase.java @@ -18,13 +18,17 @@ package org.jetbrains.plugins.groovy.lang.psi.impl; import com.intellij.extapi.psi.StubBasedPsiElementBase; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.stubs.IStubElementType; import com.intellij.psi.stubs.StubElement; import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor; import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinitionBody; +import org.jetbrains.plugins.groovy.util.GrFileIndexUtil; /** * @author ilyas @@ -65,4 +69,14 @@ public abstract class GrStubElementBase extends StubBased return getParentByTree(); } + + @NotNull + @Override + public GlobalSearchScope getResolveScope() { + final PsiFile containingFile = getContainingFile(); + final GlobalSearchScope elementScope = super.getResolveScope(); + return GrFileIndexUtil.isGroovySourceFile(containingFile) + ? elementScope + : GlobalSearchScope.fileScope(containingFile).union(elementScope); + } } diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileImpl.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileImpl.java index 825431b2a238..5974da689ce3 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileImpl.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/impl/GroovyFileImpl.java @@ -20,7 +20,6 @@ import com.intellij.lang.ASTNode; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.*; -import com.intellij.psi.impl.ElementBase; import com.intellij.psi.scope.NameHint; import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.stubs.StubElement; @@ -31,11 +30,9 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.ConcurrencyUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.ContainerUtil; -import icons.JetgroovyIcons; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.GroovyLanguage; -import org.jetbrains.plugins.groovy.extensions.GroovyScriptTypeDetector; import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes; import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes; import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; @@ -58,7 +55,6 @@ import org.jetbrains.plugins.groovy.lang.resolve.PackageSkippingProcessor; import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil; import org.jetbrains.plugins.groovy.lang.resolve.processors.ClassHint; -import javax.swing.*; import java.util.concurrent.ConcurrentMap; /** @@ -305,13 +301,6 @@ public class GroovyFileImpl extends GroovyFileBaseImpl implements GroovyFile { return calcTreeElement().getChildrenAsPsiElements(GroovyElementTypes.IMPORT_STATEMENT, GrImportStatement.ARRAY_FACTORY); } - @Override - @Nullable - public Icon getIcon(int flags) { - final Icon baseIcon = isScript() ? GroovyScriptTypeDetector.getIcon(this) : JetgroovyIcons.Groovy.Groovy_16x16; - return ElementBase.createLayeredIcon(this, baseIcon, ElementBase.transformFlags(this, flags)); - } - @Override public GrImportStatement addImportForClass(@NotNull PsiClass aClass) { try { diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/util/GrFileIndexUtil.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/util/GrFileIndexUtil.java new file mode 100644 index 000000000000..6eeba6ed90b8 --- /dev/null +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/util/GrFileIndexUtil.java @@ -0,0 +1,46 @@ +/* + * 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.groovy.util; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.FileIndexFacade; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.PsiFile; +import com.intellij.testFramework.LightVirtualFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase; + +public class GrFileIndexUtil { + + public static boolean isGroovySourceFile(@NotNull PsiFile file) { + return file instanceof GroovyFileBase && isGroovySourceFile((GroovyFileBase)file); + } + + public static boolean isGroovySourceFile(@NotNull GroovyFileBase file) { + return isInSourceFiles(file.getVirtualFile(), file.getProject()); + } + + private static boolean isInSourceFiles(@Nullable VirtualFile file, @NotNull Project project) { + if (file != null && !(file instanceof LightVirtualFile)) { + final FileIndexFacade index = FileIndexFacade.getInstance(project); + if (index.isInSource(file) || index.isInLibraryClasses(file)) { + return true; + } + } + return false; + } +} diff --git a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/ForkedGroovyc.java b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/ForkedGroovyc.java index 18bd31732657..94690e146d42 100644 --- a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/ForkedGroovyc.java +++ b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/ForkedGroovyc.java @@ -60,7 +60,7 @@ class ForkedGroovyc implements GroovycFlavor { throws Exception { List classpath = new ArrayList(); if (myOptimizeClassLoading) { - classpath.add(GroovyBuilder.getGroovyRtRoot().getPath()); + classpath.addAll(GroovyBuilder.getGroovyRtRoots()); classpath.add(ClasspathBootstrap.getResourcePath(Function.class)); classpath.add(ClasspathBootstrap.getResourcePath(UrlClassLoader.class)); classpath.add(ClasspathBootstrap.getResourceFile(THashMap.class).getPath()); diff --git a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java index 810d79a529a5..cfaef7d7add4 100644 --- a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java +++ b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/GroovyBuilder.java @@ -26,6 +26,7 @@ import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashMap; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.groovy.compiler.rt.GroovyRtConstants; import org.jetbrains.jps.ModuleChunk; import org.jetbrains.jps.ProjectPaths; import org.jetbrains.jps.builders.BuildRootIndex; @@ -485,7 +486,7 @@ public class GroovyBuilder extends ModuleLevelBuilder { final Set cp = new LinkedHashSet(); //groovy_rt.jar // IMPORTANT! must be the first in classpath - cp.add(getGroovyRtRoot().getPath()); + cp.addAll(getGroovyRtRoots()); for (File file : ProjectPaths.getCompilationClasspathFiles(chunk, chunk.containsTests(), false, false)) { cp.add(FileUtil.toCanonicalPath(file.getPath())); @@ -498,12 +499,11 @@ public class GroovyBuilder extends ModuleLevelBuilder { return cp; } - static File getGroovyRtRoot() { - File root = ClasspathBootstrap.getResourceFile(GroovyBuilder.class); - if (root.isFile()) { - return new File(root.getParentFile(), "groovy_rt.jar"); - } - return new File(root.getParentFile(), "groovy_rt"); + static List getGroovyRtRoots() { + File rt = ClasspathBootstrap.getResourceFile(GroovyBuilder.class); + File constants = ClasspathBootstrap.getResourceFile(GroovyRtConstants.class); + return Arrays.asList(new File(rt.getParentFile(), rt.isFile() ? "groovy_rt.jar" : "groovy_rt").getPath(), + new File(constants.getParentFile(), constants.isFile() ? "groovy-rt-constants.jar" : "groovy-rt-constants").getPath()); } public static boolean isGroovyFile(String path) { diff --git a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/InProcessGroovyc.java b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/InProcessGroovyc.java index 566ffcb39dd4..8896accbcb00 100644 --- a/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/InProcessGroovyc.java +++ b/plugins/groovy/jps-plugin/src/org/jetbrains/jps/incremental/groovy/InProcessGroovyc.java @@ -30,6 +30,7 @@ import com.intellij.util.lang.UrlClassLoader; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.groovy.compiler.rt.GroovyRtConstants; +import org.jetbrains.groovy.compiler.rt.ClassDependencyLoader; import java.io.*; import java.lang.reflect.Method; @@ -37,10 +38,7 @@ import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; import java.net.URLClassLoader; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Queue; +import java.util.*; import java.util.concurrent.*; import java.util.regex.Pattern; @@ -209,20 +207,21 @@ class InProcessGroovyc implements GroovycFlavor { return pair.second; } + final ClassDependencyLoader checkWellFormed = new ClassDependencyLoader(); UrlClassLoader groovyAllLoader = UrlClassLoader.build(). - urls(toUrls(Arrays.asList(GroovyBuilder.getGroovyRtRoot().getPath(), groovyAll))).allowLock(). - useCache(ourLoaderCachePool, new UrlClassLoader.CachingCondition() { - @Override - public boolean shouldCacheData( - @NotNull URL url) { - return true; - } - }).get(); + urls(toUrls(ContainerUtil.concat(GroovyBuilder.getGroovyRtRoots(), Collections.singletonList(groovyAll)))).allowLock(). + useCache(ourLoaderCachePool, new UrlClassLoader.CachingCondition() { + @Override + public boolean shouldCacheData( + @NotNull URL url) { + return true; + } + }).get(); ClassLoader wrapper = new URLClassLoader(new URL[0], groovyAllLoader) { @Override protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { try { - return super.loadClass(name, resolve); + return checkWellFormed.loadDependencies(super.loadClass(name, resolve)); } catch (NoClassDefFoundError e) { // We might attempt to load some class in groovy-all.jar that depends on a class from another library @@ -239,6 +238,9 @@ class InProcessGroovyc implements GroovycFlavor { return wrapper; } + + + @NotNull private static List toUrls(Collection paths) throws MalformedURLException { List urls = ContainerUtil.newArrayList(); diff --git a/plugins/groovy/rt-constants/src/org/jetbrains/groovy/compiler/rt/ClassDependencyLoader.java b/plugins/groovy/rt-constants/src/org/jetbrains/groovy/compiler/rt/ClassDependencyLoader.java new file mode 100644 index 000000000000..20ff457193d7 --- /dev/null +++ b/plugins/groovy/rt-constants/src/org/jetbrains/groovy/compiler/rt/ClassDependencyLoader.java @@ -0,0 +1,110 @@ +/* + * 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.groovy.compiler.rt; + +import java.lang.reflect.*; +import java.util.HashSet; +import java.util.Set; + +/** + * @author peter + */ +public class ClassDependencyLoader { + + /** + * @param aClass + * @return aClass + * @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()); + return aClass; + } + + private void loadTypeDependencies(Type aClass, Set visited) throws ClassNotFoundException { + if (aClass instanceof Class) { + loadClassDependencies((Class)aClass, visited); + } + else if (aClass instanceof ParameterizedType) { + loadTypeDependencies(((ParameterizedType)aClass).getOwnerType(), visited); + for (Type type : ((ParameterizedType)aClass).getActualTypeArguments()) { + loadTypeDependencies(type, visited); + } + } + else if (aClass instanceof WildcardType) { + for (Type type : ((WildcardType)aClass).getLowerBounds()) { + loadTypeDependencies(type, visited); + } + for (Type type : ((WildcardType)aClass).getUpperBounds()) { + loadTypeDependencies(type, visited); + } + } + else if (aClass instanceof GenericArrayType) { + loadTypeDependencies(((GenericArrayType)aClass).getGenericComponentType(), visited); + } + } + + protected void loadClassDependencies(Class aClass, Set visited) throws ClassNotFoundException { + String name = aClass.getName(); + if (visited.add(aClass)) { + try { + for (Method method : aClass.getDeclaredMethods()) { + loadTypeDependencies(method.getGenericReturnType(), visited); + for (Type type : method.getGenericExceptionTypes()) { + loadTypeDependencies(type, visited); + } + for (Type type : method.getGenericParameterTypes()) { + loadTypeDependencies(type, visited); + } + } + for (Constructor method : aClass.getDeclaredConstructors()) { + for (Type type : method.getGenericExceptionTypes()) { + loadTypeDependencies(type, visited); + } + for (Type type : method.getGenericParameterTypes()) { + loadTypeDependencies(type, visited); + } + } + + for (Field field : aClass.getDeclaredFields()) { + loadTypeDependencies(field.getGenericType(), visited); + } + + Type superclass = aClass.getGenericSuperclass(); + if (superclass != null) { + loadClassDependencies(aClass, visited); + } + + for (Type intf : aClass.getGenericInterfaces()) { + loadTypeDependencies(intf, visited); + } + + aClass.getAnnotations(); + Package aPackage = aClass.getPackage(); + if (aPackage != null) { + aPackage.getAnnotations(); + } + } + catch (LinkageError e) { + throw new ClassNotFoundException(name); + } + catch (TypeNotPresentException e) { + throw new ClassNotFoundException(name); + } + } + } + +} diff --git a/plugins/groovy/rt/src/org/jetbrains/groovy/compiler/rt/DependentGroovycRunner.java b/plugins/groovy/rt/src/org/jetbrains/groovy/compiler/rt/DependentGroovycRunner.java index 12bfbc87b913..7f1ab1ae96fa 100644 --- a/plugins/groovy/rt/src/org/jetbrains/groovy/compiler/rt/DependentGroovycRunner.java +++ b/plugins/groovy/rt/src/org/jetbrains/groovy/compiler/rt/DependentGroovycRunner.java @@ -33,7 +33,6 @@ import org.codehaus.groovy.tools.javac.JavaCompiler; import org.codehaus.groovy.tools.javac.JavaCompilerFactory; import java.io.*; -import java.lang.reflect.*; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.*; @@ -467,6 +466,14 @@ public class DependentGroovycRunner { } static GroovyClassLoader buildClassLoaderFor(final CompilerConfiguration compilerConfiguration, final AstAwareResourceLoader resourceLoader) { + final ClassDependencyLoader checkWellFormed = new ClassDependencyLoader() { + @Override + protected void loadClassDependencies(Class aClass, Set visited) throws ClassNotFoundException { + if (resourceLoader.getSourceFile(aClass.getName()) == null) return; + super.loadClassDependencies(aClass, visited); + } + }; + GroovyClassLoader classLoader = AccessController.doPrivileged(new PrivilegedAction() { public GroovyClassLoader run() { return new GroovyClassLoader(Thread.currentThread().getContextClassLoader(), compilerConfiguration) { @@ -482,83 +489,7 @@ public class DependentGroovycRunner { catch (LinkageError e) { throw new RuntimeException("Problem loading class " + name, e); } - - ensureWellFormed(aClass, new HashSet()); - - return aClass; - } - - private void ensureWellFormed(Type aClass, Set visited) throws ClassNotFoundException { - if (aClass instanceof Class) { - ensureWellFormed((Class)aClass, visited); - } - else if (aClass instanceof ParameterizedType) { - ensureWellFormed(((ParameterizedType)aClass).getOwnerType(), visited); - for (Type type : ((ParameterizedType)aClass).getActualTypeArguments()) { - ensureWellFormed(type, visited); - } - } - else if (aClass instanceof WildcardType) { - for (Type type : ((WildcardType)aClass).getLowerBounds()) { - ensureWellFormed(type, visited); - } - for (Type type : ((WildcardType)aClass).getUpperBounds()) { - ensureWellFormed(type, visited); - } - } - else if (aClass instanceof GenericArrayType) { - ensureWellFormed(((GenericArrayType)aClass).getGenericComponentType(), visited); - } - } - - private void ensureWellFormed(Class aClass, Set visited) throws ClassNotFoundException { - String name = aClass.getName(); - if (resourceLoader.getSourceFile(name) != null && visited.add(aClass)) { - try { - for (Method method : aClass.getDeclaredMethods()) { - ensureWellFormed(method.getGenericReturnType(), visited); - for (Type type : method.getGenericExceptionTypes()) { - ensureWellFormed(type, visited); - } - for (Type type : method.getGenericParameterTypes()) { - ensureWellFormed(type, visited); - } - } - for (Constructor method : aClass.getDeclaredConstructors()) { - for (Type type : method.getGenericExceptionTypes()) { - ensureWellFormed(type, visited); - } - for (Type type : method.getGenericParameterTypes()) { - ensureWellFormed(type, visited); - } - } - - for (Field field : aClass.getDeclaredFields()) { - ensureWellFormed(field.getGenericType(), visited); - } - - Type superclass = aClass.getGenericSuperclass(); - if (superclass != null) { - ensureWellFormed(aClass, visited); - } - - for (Type intf : aClass.getGenericInterfaces()) { - ensureWellFormed(intf, visited); - } - - aClass.getAnnotations(); - Package aPackage = aClass.getPackage(); - if (aPackage != null) { - aPackage.getAnnotations(); - } - } - catch (LinkageError e) { - throw new ClassNotFoundException(name); - } - catch (TypeNotPresentException e) { - throw new ClassNotFoundException(name); - } - } + return checkWellFormed.loadDependencies(aClass); } }; } diff --git a/plugins/groovy/src/META-INF/plugin.xml b/plugins/groovy/src/META-INF/plugin.xml index 21e305ffa2e8..ec5c22850fb7 100644 --- a/plugins/groovy/src/META-INF/plugin.xml +++ b/plugins/groovy/src/META-INF/plugin.xml @@ -230,7 +230,6 @@ - - + @@ -556,7 +555,7 @@ - + diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyDocumentationProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyDocumentationProvider.java index be2e8315d780..98d15e75866e 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyDocumentationProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/documentation/GroovyDocumentationProvider.java @@ -393,7 +393,7 @@ public class GroovyDocumentationProvider implements CodeDocumentationProvider, E @Override public boolean hasDocumentationFor(PsiElement element, PsiElement originalElement) { - return CompositeDocumentationProvider.hasUrlsFor(this, element, originalElement); + return CompositeDocumentationProvider.hasBrowsableUrlsFor(this, element, originalElement); } @Override diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties index dd8b9cc181ad..1a4703f88034 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringBundle.properties @@ -139,7 +139,7 @@ is.not.class.name=''{0}'' is not class name target.class.must.not.be.script=Target class must not be a script rename.is.not.applicable.to.implicit.elements=Implicit elements cannot be renamed rename.member=Rename {0} -rename.property=Rename property {0} +rename.property=Rename property ''{0}'' cannot.introduce.field.in.script=There is no class in the scope cannot.introduce.field.in.interface=Cannot introduce field in interface expression.contains.errors=Expression contains errors diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringSupportProvider.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringSupportProvider.java index adae76ee8374..4bb5044ae034 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringSupportProvider.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/GroovyRefactoringSupportProvider.java @@ -29,6 +29,7 @@ import com.intellij.refactoring.memberPullUp.JavaPullUpHandler; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField; import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrLabeledStatement; @@ -105,7 +106,7 @@ public class GroovyRefactoringSupportProvider extends RefactoringSupportProvider @Override public boolean isMemberInplaceRenameAvailable(@NotNull PsiElement element, @Nullable PsiElement context) { - if (context == null) return false; + if (context == null || context.getContainingFile() instanceof GroovyFile) return false; PsiElement parent = context.getParent(); //don't try to inplace rename aliased imported references diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/rename/RenamePropertyUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/rename/RenamePropertyUtil.java index 64352851fcec..949d38275cda 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/rename/RenamePropertyUtil.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/rename/RenamePropertyUtil.java @@ -79,7 +79,7 @@ public class RenamePropertyUtil { ContainerUtil.addAll(property, GroovyPropertyUtils.getAllGetters(containingClass, name, isStatic, false)); ContainerUtil.addAll(property, GroovyPropertyUtils.getAllSetters(containingClass, name, isStatic, false)); - for (Iterator iterator = property.iterator(); iterator.hasNext();) { + for (Iterator iterator = property.iterator(); iterator.hasNext(); ) { if (iterator.next() instanceof GrAccessorMethod) iterator.remove(); } @@ -169,7 +169,7 @@ public class RenamePropertyUtil { } private String getDescription() { - return (UsageViewUtil.getType(myMember) + " " + myMember.getName()).trim(); + return String.format("%s '%s'", UsageViewUtil.getType(myMember), myMember.getName()); } public boolean renameProperty() { diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/rename/inplace/GrMethodInplaceRenameHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/rename/inplace/GrMethodInplaceRenameHandler.java index 2bad31412d5a..a7b7fe1240c4 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/rename/inplace/GrMethodInplaceRenameHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/refactoring/rename/inplace/GrMethodInplaceRenameHandler.java @@ -22,6 +22,7 @@ import com.intellij.psi.PsiNameIdentifierOwner; import com.intellij.refactoring.rename.inplace.MemberInplaceRenameHandler; import com.intellij.refactoring.rename.inplace.MemberInplaceRenamer; import org.jetbrains.annotations.NotNull; +import org.jetbrains.plugins.groovy.lang.psi.GroovyFile; import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrMethod; /** @@ -31,8 +32,7 @@ public class GrMethodInplaceRenameHandler extends MemberInplaceRenameHandler { @Override protected boolean isAvailable(PsiElement element, Editor editor, PsiFile file) { if (!editor.getSettings().isVariableInplaceRenameEnabled()) return false; - - return element instanceof GrMethod; + return element instanceof GrMethod && file instanceof GroovyFile; } @NotNull diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy index a0a7277d92c4..bd9aff737765 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyCompilerTest.groovy @@ -884,10 +884,12 @@ class AppTest { assertTrue(exceptionFound.get()); } - public void "test extend GroovyTestCase"() { + public void "test extend groovy classes with additional dependencies"() { PsiTestUtil.addLibrary(myModule, "junit", GroovyFacetUtil.libDirectory, "junit.jar"); + PsiTestUtil.addLibrary(myModule, "cli", FileUtil.toCanonicalPath(PluginPathManager.getPluginHomePath("groovy") + "/../../build/lib"), "commons-cli-1.2.jar"); myFixture.addFileToProject("a.groovy", "class Foo extends GroovyTestCase {}") + myFixture.addFileToProject("b.groovy", "class Bar extends CliBuilder {}") assertEmpty(make()) } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyDebuggerTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyDebuggerTest.groovy index 72bdcf232f85..d8378404702f 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyDebuggerTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/compiler/GroovyDebuggerTest.groovy @@ -101,6 +101,10 @@ class GroovyDebuggerTest extends GroovyCompilerTestCase { try { cl.call() } + catch (Throwable t) { + t.printStackTrace() + throw t + } finally { def handler = debugProcess.processHandler resume() diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/ArgumentCastTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/ArgumentCastTest.groovy index cf473d6d5cd8..64aa46669947 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/ArgumentCastTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/intentions/ArgumentCastTest.groovy @@ -65,4 +65,15 @@ foo('a', 'a') foo('', g:4 ) ''', 'Cast', GroovyAssignabilityCheckInspection) } + + // TODO + void ignoredestNamedArguments() { + doTextTest ''' +def foo(a, int b, c) {} +foo('a', b: 1, 1) +''', "Cast 1st parameter to int", ''' +def foo(a, int b, c) {} +foo('a' as int, b: 1, 1) +''', GroovyAssignabilityCheckInspection + } } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/code/cfg/BasicBlock.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/code/cfg/BasicBlock.java index 28e0ae80eaa4..2e29529da63d 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/code/cfg/BasicBlock.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/code/cfg/BasicBlock.java @@ -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 succs = new ArrayList(); - private List instrOldOffsets = new ArrayList(); + private final List instrOldOffsets = new ArrayList(); private List predExceptions = new ArrayList(); private List succExceptions = new ArrayList(); - - 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(instrOldOffsets)); + block.instrOldOffsets.addAll(instrOldOffsets); return block; } @@ -220,10 +215,6 @@ public class BasicBlock implements IGraphNode { return instrOldOffsets; } - public void setInstrOldOffsets(List instrInds) { - this.instrOldOffsets = instrInds; - } - public List getPredecessors() { List lst = new ArrayList(preds); lst.addAll(predExceptions); diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/code/cfg/ControlFlowGraph.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/code/cfg/ControlFlowGraph.java index 8e66fddbb4d7..2f4761e8dce3 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/code/cfg/ControlFlowGraph.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/code/cfg/ControlFlowGraph.java @@ -296,7 +296,7 @@ public class ControlFlowGraph implements CodeConstants { VBStyleCollection col = new VBStyleCollection(); InstructionSequence currseq = null; - ArrayList lstOffs = null; + List 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(); + 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()) { diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java index 502e9897582a..03318a91e957 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/ClassWriter.java @@ -534,8 +534,8 @@ public class ClassWriter { indent += 1; } + RootStatement root = classWrapper.getMethodWrapper(mt.getName(), mt.getDescriptor()).root; if (!methodWrapper.decompiledWithErrors) { - RootStatement root = classWrapper.getMethodWrapper(mt.getName(), mt.getDescriptor()).root; if (root != null) { // check for existence try { buffer.append(root.toJava(indent, tracer)); @@ -553,12 +553,13 @@ public class ClassWriter { buffer.appendLineSeparator(); } + if (root != null) { + tracer.addMapping(root.getDummyExit().bytecode); + } + if (!codeOnly) { indent -= 1; - - buffer.appendIndent(indent); - buffer.append('}'); - buffer.appendLineSeparator(); + buffer.appendIndent(indent).append('}').appendLineSeparator(); } } finally { @@ -869,6 +870,9 @@ public class ClassWriter { tracer.incrementCurrentSourceLine(); } + if (root != null) { + tracer.addMapping(root.getDummyExit().bytecode); + } buffer.appendIndent(indent).append('}').appendLineSeparator(); tracer.incrementCurrentSourceLine(); } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeMappingTracer.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeMappingTracer.java index 9827ffc75001..84ca0b71e287 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeMappingTracer.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeMappingTracer.java @@ -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. @@ -89,12 +89,20 @@ public class BytecodeMappingTracer { this.lineNumberTable = lineNumberTable; } + private final Set unmappedLines = new HashSet(); + + public Set getUnmappedLines() { + return unmappedLines; + } + public Map getOriginalLinesMapping() { if (lineNumberTable == null) { return Collections.emptyMap(); } Map res = new HashMap(); + + // first match offsets from line number table int[] data = lineNumberTable.getRawData(); for (int i = 0; i < data.length; i += 2) { int originalOffset = data[i]; @@ -103,11 +111,17 @@ public class BytecodeMappingTracer { if (newLine != null) { res.put(originalLine, newLine); } + else { + unmappedLines.add(originalLine); + } } + + // now match offsets from decompiler mapping for (Entry 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); } } return res; diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeSourceMapper.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeSourceMapper.java index 26e6f78cf0f1..8d3770b8923a 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeSourceMapper.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/main/collectors/BytecodeSourceMapper.java @@ -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 @@ public class BytecodeSourceMapper { // original line to decompiled line private final Map linesMapping = new HashMap(); + private final Set unmappedLines = new TreeSet(); public void addMapping(String className, String methodName, int bytecodeOffset, int sourceLine) { Map> class_mapping = mapping.get(className); @@ -53,6 +54,7 @@ public class BytecodeSourceMapper { addMapping(className, methodName, entry.getKey(), entry.getValue()); } linesMapping.putAll(tracer.getOriginalLinesMapping()); + unmappedLines.addAll(tracer.getUnmappedLines()); } public void dumpMapping(TextBuffer buffer, boolean offsetsToHex) { @@ -97,7 +99,16 @@ public class BytecodeSourceMapper { buffer.append("Lines mapping:").appendLineSeparator(); Map sorted = new TreeMap(linesMapping); for (Entry entry : sorted.entrySet()) { - buffer.append(entry.getKey()).append(" <-> ").append(entry.getValue()+ offset_total + 1).appendLineSeparator(); + buffer.append(entry.getKey()).append(" <-> ").append(entry.getValue() + offset_total + 1).appendLineSeparator(); + } + + if (!unmappedLines.isEmpty()) { + buffer.append("Not mapped:").appendLineSeparator(); + for (Integer line : unmappedLines) { + if (!linesMapping.containsKey(line)) { + buffer.append(line).appendLineSeparator(); + } + } } } @@ -121,6 +132,7 @@ public class BytecodeSourceMapper { int i = 0; for (Entry entry : linesMapping.entrySet()) { res[i] = entry.getKey(); + unmappedLines.remove(entry.getKey()); res[i + 1] = entry.getValue() + offset_total + 1; // make it 1 based i += 2; } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/DomHelper.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/DomHelper.java index 952732631378..c93be38f6aba 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/DomHelper.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/DomHelper.java @@ -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. @@ -46,8 +46,7 @@ public class DomHelper { // head statement Statement firstst = stats.getWithKey(firstblock.id); // dummy exit statement - Statement dummyexit = new Statement(); - dummyexit.type = Statement.TYPE_DUMMYEXIT; + DummyExitStatement dummyexit = new DummyExitStatement(); Statement general; if (stats.size() > 1 || firstblock.isSuccessor(firstblock)) { // multiple basic blocks or an infinite loop of one block diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/ExitHelper.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/ExitHelper.java index a7ccf24e3a4d..d467cdcc200f 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/ExitHelper.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/ExitHelper.java @@ -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. @@ -247,7 +247,9 @@ public class ExitHelper { boolean res = false; - for (StatEdge edge : root.getDummyExit().getAllPredecessorEdges()) { + DummyExitStatement dummyExit = root.getDummyExit(); + + for (StatEdge edge : dummyExit.getAllPredecessorEdges()) { if (!edge.explicit) { Statement source = edge.getSource(); List lstExpr = source.getExprents(); @@ -257,6 +259,7 @@ public class ExitHelper { ExitExprent ex = (ExitExprent)expr; if (ex.getExitType() == ExitExprent.EXIT_RETURN && ex.getValue() == null) { // remove redundant return + dummyExit.addBytecodeOffsets(ex.bytecode); lstExpr.remove(lstExpr.size() - 1); res = true; } diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/FinallyProcessor.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/FinallyProcessor.java index 9d21784fa5c0..a49f8f3888e2 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/FinallyProcessor.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/FinallyProcessor.java @@ -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 oldOffsets = new LinkedList(); 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 lstTemp = new ArrayList(); 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 diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/DummyExitStatement.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/DummyExitStatement.java new file mode 100644 index 000000000000..ba8218263a2b --- /dev/null +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/DummyExitStatement.java @@ -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 org.jetbrains.java.decompiler.modules.decompiler.stats; + +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +/** + * @author egor + */ +public class DummyExitStatement extends Statement { + public Set bytecode = null; // offsets of bytecode instructions mapped to dummy exit + + public DummyExitStatement() { + type = Statement.TYPE_DUMMYEXIT; + } + + public void addBytecodeOffsets(Collection bytecodeOffsets) { + if (bytecodeOffsets != null && !bytecodeOffsets.isEmpty()) { + if (bytecode == null) { + bytecode = new HashSet(bytecodeOffsets); + } + else { + bytecode.addAll(bytecodeOffsets); + } + } + } +} diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/RootStatement.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/RootStatement.java index 42323fc40dc0..7193f9a787a2 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/RootStatement.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/RootStatement.java @@ -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,9 +22,9 @@ import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor; public class RootStatement extends Statement { - private Statement dummyExit; + private DummyExitStatement dummyExit; - public RootStatement(Statement head, Statement dummyExit) { + public RootStatement(Statement head, DummyExitStatement dummyExit) { type = Statement.TYPE_ROOT; @@ -39,11 +39,11 @@ public class RootStatement extends Statement { return ExprProcessor.listToJava(varDefinitions, indent, tracer).append(first.toJava(indent, tracer)); } - public Statement getDummyExit() { + public DummyExitStatement getDummyExit() { return dummyExit; } - public void setDummyExit(Statement dummyExit) { + public void setDummyExit(DummyExitStatement dummyExit) { this.dummyExit = dummyExit; } } diff --git a/plugins/java-decompiler/engine/testData/results/InvalidMethodSignature.dec b/plugins/java-decompiler/engine/testData/results/InvalidMethodSignature.dec index 24b7c852219b..7b4f8c504005 100644 --- a/plugins/java-decompiler/engine/testData/results/InvalidMethodSignature.dec +++ b/plugins/java-decompiler/engine/testData/results/InvalidMethodSignature.dec @@ -12,23 +12,24 @@ class i implements bg { private final b b; i(b var1, j var2) { - this.b = var1; - this.a = var2;// 1 + this.b = var1;// 1 + this.a = var2; } public void a(c var1, k var2, boolean var3) { File var4 = this.a.b().a(var1);// 2 b.a(this.b).add(var4);// 3 - } + }// 4 public void a(a.a.a.a.c.b var1) { - } + }// 0 } class 'a/a/a/a/e/f/i' { method ' (La/a/a/a/e/f/b;La/a/a/a/c/j;)V' { 2 14 7 15 + e 16 } method 'a (La/a/a/a/c/c;La/a/a/a/a/k;Z)V' { @@ -39,10 +40,17 @@ class 'a/a/a/a/e/f/i' { 12 20 15 20 1a 20 + 20 21 + } + + method 'a (La/a/a/a/c/b;)V' { + 0 24 } } Lines mapping: -1 <-> 16 +0 <-> 25 +1 <-> 15 2 <-> 20 3 <-> 21 +4 <-> 22 diff --git a/plugins/java-decompiler/engine/testData/results/TestAbstractMethods.dec b/plugins/java-decompiler/engine/testData/results/TestAbstractMethods.dec index 59b102744c55..781cbfcf0bf8 100644 --- a/plugins/java-decompiler/engine/testData/results/TestAbstractMethods.dec +++ b/plugins/java-decompiler/engine/testData/results/TestAbstractMethods.dec @@ -11,7 +11,7 @@ public abstract class TestAbstractMethods { public void test2(String var1) { System.out.println(var1);// 17 - } + }// 18 } class 'pkg/TestAbstractMethods' { @@ -22,9 +22,11 @@ class 'pkg/TestAbstractMethods' { method 'test2 (Ljava/lang/String;)V' { 0 12 4 12 + 7 13 } } Lines mapping: 11 <-> 7 17 <-> 13 +18 <-> 14 diff --git a/plugins/java-decompiler/engine/testData/results/TestAmbiguousCall.dec b/plugins/java-decompiler/engine/testData/results/TestAmbiguousCall.dec index caeb41d8ed38..a48730dcfb20 100644 --- a/plugins/java-decompiler/engine/testData/results/TestAmbiguousCall.dec +++ b/plugins/java-decompiler/engine/testData/results/TestAmbiguousCall.dec @@ -2,10 +2,10 @@ package pkg; class TestAmbiguousCall { void m1(RuntimeException var1, String var2) { - } + }// 4 void m1(IllegalArgumentException var1, String var2) { - } + }// 5 void test() { IllegalArgumentException var1 = new IllegalArgumentException();// 8 @@ -14,10 +14,18 @@ class TestAmbiguousCall { IllegalArgumentException var2 = new IllegalArgumentException();// 12 this.m1((RuntimeException)var2, "RE");// 13 this.m1((IllegalArgumentException)var2, "IAE");// 14 - } + }// 15 } class 'pkg/TestAmbiguousCall' { + method 'm1 (Ljava/lang/RuntimeException;Ljava/lang/String;)V' { + 0 4 + } + + method 'm1 (Ljava/lang/IllegalArgumentException;Ljava/lang/String;)V' { + 0 7 + } + method 'test ()V' { 7 10 a 11 @@ -30,13 +38,17 @@ class 'pkg/TestAmbiguousCall' { 27 15 2a 15 2c 15 + 2f 16 } } Lines mapping: +4 <-> 5 +5 <-> 8 8 <-> 11 9 <-> 12 10 <-> 13 12 <-> 14 13 <-> 15 14 <-> 16 +15 <-> 17 diff --git a/plugins/java-decompiler/engine/testData/results/TestAmbiguousCallWithDebugInfo.dec b/plugins/java-decompiler/engine/testData/results/TestAmbiguousCallWithDebugInfo.dec index 6380d6db06a3..40f1eaf68c9b 100644 --- a/plugins/java-decompiler/engine/testData/results/TestAmbiguousCallWithDebugInfo.dec +++ b/plugins/java-decompiler/engine/testData/results/TestAmbiguousCallWithDebugInfo.dec @@ -2,10 +2,10 @@ package pkg; class TestAmbiguousCall { void m1(RuntimeException e, String s) { - } + }// 4 void m1(IllegalArgumentException e, String s) { - } + }// 5 void test() { IllegalArgumentException iae = new IllegalArgumentException();// 8 @@ -14,10 +14,18 @@ class TestAmbiguousCall { IllegalArgumentException re = new IllegalArgumentException();// 12 this.m1((RuntimeException)re, "RE");// 13 this.m1((IllegalArgumentException)re, "IAE");// 14 - } + }// 15 } class 'pkg/TestAmbiguousCall' { + method 'm1 (Ljava/lang/RuntimeException;Ljava/lang/String;)V' { + 0 4 + } + + method 'm1 (Ljava/lang/IllegalArgumentException;Ljava/lang/String;)V' { + 0 7 + } + method 'test ()V' { 7 10 a 11 @@ -30,13 +38,17 @@ class 'pkg/TestAmbiguousCall' { 27 15 2a 15 2c 15 + 2f 16 } } Lines mapping: +4 <-> 5 +5 <-> 8 8 <-> 11 9 <-> 12 10 <-> 13 12 <-> 14 13 <-> 15 14 <-> 16 +15 <-> 17 diff --git a/plugins/java-decompiler/engine/testData/results/TestAnonymousClass.dec b/plugins/java-decompiler/engine/testData/results/TestAnonymousClass.dec index d0ae4ec7102c..75d1df239bb5 100644 --- a/plugins/java-decompiler/engine/testData/results/TestAnonymousClass.dec +++ b/plugins/java-decompiler/engine/testData/results/TestAnonymousClass.dec @@ -5,26 +5,26 @@ public abstract class TestAnonymousClass { public void run() { boolean var1 = true;// 28 boolean var2 = true;// 29 - } + }// 30 }; public static final Runnable R = new Runnable() { public void run() { boolean var1 = true;// 45 boolean var2 = true;// 46 - } + }// 47 }; public static final Runnable R1 = new Runnable() { public void run() { boolean var1 = true;// 53 boolean var2 = true;// 54 - } + }// 55 }; private final TestAnonymousClass.InnerRecursive y = new TestAnonymousClass.InnerRecursive(new TestAnonymousClass.InnerRecursive((TestAnonymousClass.InnerRecursive)null) { void foo() { boolean var1 = true;// 75 boolean var2 = true;// 76 boolean var3 = true;// 77 - } + }// 78 }) { int v = 5; int t = 5; @@ -36,7 +36,7 @@ public abstract class TestAnonymousClass { boolean var1 = true;// 90 boolean var2 = true;// 91 boolean var3 = true;// 92 - } + }// 93 }) { int v = 5; int t = 5; @@ -50,32 +50,32 @@ public abstract class TestAnonymousClass { public void foo() throws Exception { boolean var1 = true;// 13 boolean var2 = true;// 14 - } + }// 15 };// 11 var2.foo();// 17 } else { System.out.println(5);// 21 } - } + }// 23 void boo() { boolean var1 = true;// 35 - } + }// 36 void zoo() { boolean var1 = true;// 39 - } + }// 40 static class InnerRecursive { TestAnonymousClass.InnerRecursive r; public InnerRecursive(TestAnonymousClass.InnerRecursive var1) { this.r = var1;// 105 - } + }// 106 void foo() { - } + }// 110 } private static class Inner { @@ -83,7 +83,7 @@ public abstract class TestAnonymousClass { public void run() { boolean var1 = true;// 66 boolean var2 = true;// 67 - } + }// 68 }; } @@ -98,6 +98,7 @@ class 'pkg/TestAnonymousClass$2' { 1 5 2 6 3 6 + 4 7 } } @@ -107,6 +108,7 @@ class 'pkg/TestAnonymousClass$3' { 1 11 2 12 3 12 + 4 13 } } @@ -116,6 +118,7 @@ class 'pkg/TestAnonymousClass$4' { 1 17 2 18 3 18 + 4 19 } } @@ -127,6 +130,7 @@ class 'pkg/TestAnonymousClass$5' { 3 24 4 25 5 25 + 6 26 } } @@ -138,6 +142,7 @@ class 'pkg/TestAnonymousClass$7' { 3 36 4 37 5 37 + 6 38 } } @@ -147,6 +152,7 @@ class 'pkg/TestAnonymousClass$1' { 1 50 2 51 3 51 + 4 52 } } @@ -158,22 +164,30 @@ class 'pkg/TestAnonymousClass' { 16 56 19 56 1a 56 + 1d 59 } method 'boo ()V' { 0 62 1 62 + 2 63 } method 'zoo ()V' { 0 66 1 66 + 2 67 } } class 'pkg/TestAnonymousClass$InnerRecursive' { method ' (Lpkg/TestAnonymousClass$InnerRecursive;)V' { 6 73 + 9 74 + } + + method 'foo ()V' { + 0 77 } } @@ -183,6 +197,7 @@ class 'pkg/TestAnonymousClass$Inner$1' { 1 83 2 84 3 84 + 4 85 } } @@ -191,22 +206,37 @@ Lines mapping: 11 <-> 54 13 <-> 51 14 <-> 52 +15 <-> 53 17 <-> 55 21 <-> 57 +23 <-> 60 28 <-> 6 29 <-> 7 +30 <-> 8 35 <-> 63 +36 <-> 64 39 <-> 67 +40 <-> 68 45 <-> 12 46 <-> 13 +47 <-> 14 53 <-> 18 54 <-> 19 +55 <-> 20 66 <-> 84 67 <-> 85 +68 <-> 86 75 <-> 24 76 <-> 25 77 <-> 26 +78 <-> 27 90 <-> 36 91 <-> 37 92 <-> 38 +93 <-> 39 105 <-> 74 +106 <-> 75 +110 <-> 78 +Not mapped: +18 +104 diff --git a/plugins/java-decompiler/engine/testData/results/TestClassCast.dec b/plugins/java-decompiler/engine/testData/results/TestClassCast.dec index 7593d6d01a57..c45fad8c954d 100644 --- a/plugins/java-decompiler/engine/testData/results/TestClassCast.dec +++ b/plugins/java-decompiler/engine/testData/results/TestClassCast.dec @@ -11,7 +11,7 @@ public class TestClassCast { } System.out.println(((List)var2).size());// 26 - } + }// 27 } class 'pkg/TestClassCast' { @@ -24,6 +24,7 @@ class 'pkg/TestClassCast' { 18 12 1c 12 21 12 + 24 13 } } @@ -32,3 +33,4 @@ Lines mapping: 23 <-> 9 24 <-> 10 26 <-> 13 +27 <-> 14 diff --git a/plugins/java-decompiler/engine/testData/results/TestClassFields.dec b/plugins/java-decompiler/engine/testData/results/TestClassFields.dec index 1415306b340d..75ece1eee7f7 100644 --- a/plugins/java-decompiler/engine/testData/results/TestClassFields.dec +++ b/plugins/java-decompiler/engine/testData/results/TestClassFields.dec @@ -6,7 +6,7 @@ public class TestClassFields { static { sizes = new int[names.length];// 26 - } + }// 27 } class 'pkg/TestClassFields' { @@ -14,8 +14,12 @@ class 'pkg/TestClassFields' { 11 7 14 7 17 7 + 1a 8 } } Lines mapping: 26 <-> 8 +27 <-> 9 +Not mapped: +25 diff --git a/plugins/java-decompiler/engine/testData/results/TestClassLambda.dec b/plugins/java-decompiler/engine/testData/results/TestClassLambda.dec index 7dcada9eef0d..4b6e65f1b83f 100644 --- a/plugins/java-decompiler/engine/testData/results/TestClassLambda.dec +++ b/plugins/java-decompiler/engine/testData/results/TestClassLambda.dec @@ -20,8 +20,8 @@ public class TestClassLambda { var1.forEach((var2x) -> {// 32 int var3 = 2 * var2x.intValue();// 33 System.out.println(var3 + var2 + this.field);// 34 - }); - } + });// 35 + }// 36 public void testLambda1() { int var1 = (int)Math.random();// 39 @@ -31,26 +31,26 @@ public class TestClassLambda { Runnable var3 = () -> { System.out.println("hello2" + var1); };// 41 - } + }// 42 public void testLambda2() { reduce((var0, var1) -> {// 45 return Math.max(var0, var1); }); - } + }// 46 public void testLambda3() { reduce(Math::max);// 49 - } + }// 50 public void testLambda4() { reduce(TestClassLambda::localMax);// 53 - } + }// 54 public void testLambda5() { String var1 = "abcd";// 57 function(var1::toString);// 58 - } + }// 59 public void testLambda6() { ArrayList var1 = new ArrayList();// 62 @@ -59,11 +59,11 @@ public class TestClassLambda { var1.removeIf((var2x) -> {// 65 return var2 >= var2x.length() && var2x.length() <= var3; }); - } + }// 66 public static void testLambda7(Annotation[] var0) { Arrays.stream(var0).map(Annotation::annotationType);// 69 - } + }// 70 public static OptionalInt reduce(IntBinaryOperator var0) { return null;// 73 @@ -85,7 +85,7 @@ public class TestClassLambda { };// 87 System.out.println("hello1" + var1);// 88 };// 86 - } + }// 90 } class 'pkg/TestClassLambda' { @@ -99,6 +99,7 @@ class 'pkg/TestClassLambda' { e 21 11 21 12 21 + 15 22 } method 'testLambda ()V' { @@ -122,6 +123,7 @@ class 'pkg/TestClassLambda' { 40 18 41 18 4a 19 + 4f 23 } method 'lambda$testLambda1$1 (I)V' { @@ -129,6 +131,7 @@ class 'pkg/TestClassLambda' { a 28 13 28 16 28 + 19 29 } method 'lambda$testLambda1$2 (I)V' { @@ -136,6 +139,7 @@ class 'pkg/TestClassLambda' { a 31 13 31 16 31 + 19 32 } method 'testLambda1 ()V' { @@ -144,6 +148,7 @@ class 'pkg/TestClassLambda' { 4 26 b 29 12 32 + 13 33 } method 'lambda$testLambda2$3 (II)I' { @@ -153,20 +158,24 @@ class 'pkg/TestClassLambda' { method 'testLambda2 ()V' { 5 36 + 9 39 } method 'testLambda3 ()V' { 5 42 + 9 43 } method 'testLambda4 ()V' { 5 46 + 9 47 } method 'testLambda5 ()V' { 0 50 2 50 e 51 + 12 52 } method 'lambda$testLambda6$4 (IILjava/lang/String;)Z' { @@ -186,11 +195,13 @@ class 'pkg/TestClassLambda' { 18 57 19 57 22 58 + 28 61 } method 'testLambda7 ([Ljava/lang/annotation/Annotation;)V' { 1 64 9 64 + f 65 } method 'reduce (Ljava/util/function/IntBinaryOperator;)Ljava/util/OptionalInt;' { @@ -214,6 +225,7 @@ class 'pkg/TestClassLambda' { a 83 13 83 16 83 + 19 84 } method 'lambda$nestedLambdas$6 (I)V' { @@ -222,12 +234,14 @@ class 'pkg/TestClassLambda' { 11 85 1a 85 1d 85 + 20 86 } method 'nestedLambdas ()V' { 0 80 1 80 8 86 + 9 87 } } @@ -237,19 +251,28 @@ Lines mapping: 32 <-> 20 33 <-> 21 34 <-> 22 +35 <-> 23 +36 <-> 24 39 <-> 27 40 <-> 30 41 <-> 33 +42 <-> 34 45 <-> 37 +46 <-> 40 49 <-> 43 +50 <-> 44 53 <-> 47 +54 <-> 48 57 <-> 51 58 <-> 52 +59 <-> 53 62 <-> 56 63 <-> 57 64 <-> 58 65 <-> 59 +66 <-> 62 69 <-> 65 +70 <-> 66 73 <-> 69 77 <-> 73 81 <-> 77 @@ -257,3 +280,5 @@ Lines mapping: 86 <-> 87 87 <-> 85 88 <-> 86 +89 <-> 87 +90 <-> 88 diff --git a/plugins/java-decompiler/engine/testData/results/TestClassLoop.dec b/plugins/java-decompiler/engine/testData/results/TestClassLoop.dec index f3bf0e07304d..060fcec822e7 100644 --- a/plugins/java-decompiler/engine/testData/results/TestClassLoop.dec +++ b/plugins/java-decompiler/engine/testData/results/TestClassLoop.dec @@ -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,8 +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: +39 +54 diff --git a/plugins/java-decompiler/engine/testData/results/TestClassNestedInitializer.dec b/plugins/java-decompiler/engine/testData/results/TestClassNestedInitializer.dec index b9fa69cdb22e..0576e74a1d8f 100644 --- a/plugins/java-decompiler/engine/testData/results/TestClassNestedInitializer.dec +++ b/plugins/java-decompiler/engine/testData/results/TestClassNestedInitializer.dec @@ -10,13 +10,14 @@ public class TestClassNestedInitializer { } };// 22 System.out.println(var1.secret);// 23 - } + }// 24 } class 'pkg/TestClassNestedInitializer$1' { method ' (Lpkg/TestClassNestedInitializer;)V' { a 8 c 8 + f 9 } } @@ -26,9 +27,11 @@ class 'pkg/TestClassNestedInitializer' { 9 11 d 11 10 11 + 13 12 } } Lines mapping: 22 <-> 11 23 <-> 12 +24 <-> 13 diff --git a/plugins/java-decompiler/engine/testData/results/TestClassSimpleBytecodeMapping.dec b/plugins/java-decompiler/engine/testData/results/TestClassSimpleBytecodeMapping.dec index b6b6bba690cb..c450205b4de4 100644 --- a/plugins/java-decompiler/engine/testData/results/TestClassSimpleBytecodeMapping.dec +++ b/plugins/java-decompiler/engine/testData/results/TestClassSimpleBytecodeMapping.dec @@ -6,7 +6,7 @@ public class TestClassSimpleBytecodeMapping { this.run(new Runnable() {// 14 public void run() { System.out.println("Runnable");// 17 - } + }// 18 }); this.test2("1");// 21 if(Math.random() > 0.0D) {// 23 @@ -27,22 +27,22 @@ public class TestClassSimpleBytecodeMapping { System.out.println("Finally");// 38 } - } + }// 40 void run(Runnable var1) { var1.run();// 49 - } + }// 50 public class InnerClass2 { public void print() { System.out.println("Inner2");// 54 - } + }// 55 } public class InnerClass { public void print() { System.out.println("Inner");// 44 - } + }// 45 } } @@ -51,6 +51,7 @@ class 'pkg/TestClassSimpleBytecodeMapping$1' { 0 7 3 7 5 7 + 8 8 } } @@ -85,10 +86,12 @@ class 'pkg/TestClassSimpleBytecodeMapping' { 23 26 24 26 27 26 + 2e 29 } method 'run (Ljava/lang/Runnable;)V' { 1 32 + 6 33 } } @@ -97,6 +100,7 @@ class 'pkg/TestClassSimpleBytecodeMapping$InnerClass2' { 0 37 3 37 5 37 + 8 38 } } @@ -105,6 +109,7 @@ class 'pkg/TestClassSimpleBytecodeMapping$InnerClass' { 0 43 3 43 5 43 + 8 44 } } @@ -112,6 +117,7 @@ Lines mapping: 12 <-> 5 14 <-> 6 17 <-> 8 +18 <-> 9 21 <-> 11 23 <-> 12 24 <-> 13 @@ -121,6 +127,13 @@ Lines mapping: 34 <-> 23 36 <-> 25 38 <-> 27 +40 <-> 30 44 <-> 44 +45 <-> 45 49 <-> 33 +50 <-> 34 54 <-> 38 +55 <-> 39 +Not mapped: +35 +39 diff --git a/plugins/java-decompiler/engine/testData/results/TestClassSwitch.dec b/plugins/java-decompiler/engine/testData/results/TestClassSwitch.dec index 695350fad6b6..d8cb7242db57 100644 --- a/plugins/java-decompiler/engine/testData/results/TestClassSwitch.dec +++ b/plugins/java-decompiler/engine/testData/results/TestClassSwitch.dec @@ -10,7 +10,7 @@ public class TestClassSwitch { case 13: System.out.println(13);// 24 } - } + }// 25 } class 'pkg/TestClassSwitch' { @@ -19,6 +19,7 @@ class 'pkg/TestClassSwitch' { 1c 10 1f 10 21 10 + 24 12 25 6 28 6 29 6 @@ -29,5 +30,6 @@ class 'pkg/TestClassSwitch' { Lines mapping: 22 <-> 5 24 <-> 11 +25 <-> 13 27 <-> 7 29 <-> 9 diff --git a/plugins/java-decompiler/engine/testData/results/TestClassTypes.dec b/plugins/java-decompiler/engine/testData/results/TestClassTypes.dec index f2a3fdbbfbea..4e633b9fc9dc 100644 --- a/plugins/java-decompiler/engine/testData/results/TestClassTypes.dec +++ b/plugins/java-decompiler/engine/testData/results/TestClassTypes.dec @@ -17,7 +17,7 @@ public class TestClassTypes { System.out.println();// 36 } - } + }// 38 public boolean testBit(int var1) { return (var1 & 1) == 1;// 41 @@ -36,7 +36,7 @@ public class TestClassTypes { System.out.println("3");// 55 } - } + }// 57 public void testAssignmentType(List var1) { Object var2 = var1;// 61 @@ -45,7 +45,7 @@ public class TestClassTypes { } System.out.println(((List)var2).size());// 67 - } + }// 68 } class 'pkg/TestClassTypes' { @@ -72,6 +72,7 @@ class 'pkg/TestClassTypes' { 23 15 26 16 29 16 + 2c 19 } method 'testBit (I)Z' { @@ -92,6 +93,7 @@ class 'pkg/TestClassTypes' { 42 35 45 35 47 35 + 4a 38 } method 'testAssignmentType (Ljava/util/List;)V' { @@ -103,6 +105,7 @@ class 'pkg/TestClassTypes' { 18 46 1c 46 21 46 + 24 47 } } @@ -115,12 +118,18 @@ Lines mapping: 32 <-> 13 35 <-> 16 36 <-> 17 +38 <-> 20 41 <-> 23 46 <-> 27 48 <-> 29 51 <-> 32 55 <-> 36 +57 <-> 39 61 <-> 42 63 <-> 43 64 <-> 44 67 <-> 47 +68 <-> 48 +Not mapped: +49 +52 diff --git a/plugins/java-decompiler/engine/testData/results/TestClassVar.dec b/plugins/java-decompiler/engine/testData/results/TestClassVar.dec index cedd9c0d80a0..37aa5ece1e8f 100644 --- a/plugins/java-decompiler/engine/testData/results/TestClassVar.dec +++ b/plugins/java-decompiler/engine/testData/results/TestClassVar.dec @@ -16,7 +16,7 @@ public class TestClassVar { } } - } + }// 37 public Long testFieldSSAU1() { return new Long((long)(this.field_int++));// 40 @@ -36,7 +36,7 @@ public class TestClassVar { } } - } + }// 58 } class 'pkg/TestClassVar' { @@ -50,6 +50,8 @@ class 'pkg/TestClassVar' { 20 11 26 12 29 12 + 2e 7 + 34 18 } method 'testFieldSSAU1 ()Ljava/lang/Long;' { @@ -69,6 +71,7 @@ class 'pkg/TestClassVar' { 1c 33 1f 34 22 34 + 28 38 } } @@ -77,6 +80,7 @@ Lines mapping: 29 <-> 10 32 <-> 12 33 <-> 13 +37 <-> 19 40 <-> 22 45 <-> 26 47 <-> 28 @@ -84,3 +88,6 @@ Lines mapping: 51 <-> 30 54 <-> 34 55 <-> 35 +58 <-> 39 +Not mapped: +57 diff --git a/plugins/java-decompiler/engine/testData/results/TestCodeConstructs.dec b/plugins/java-decompiler/engine/testData/results/TestCodeConstructs.dec index eeb9c19a91e2..fefd4212a729 100644 --- a/plugins/java-decompiler/engine/testData/results/TestCodeConstructs.dec +++ b/plugins/java-decompiler/engine/testData/results/TestCodeConstructs.dec @@ -5,7 +5,7 @@ class TestCodeConstructs { void expressions() { (new String()).hashCode();// 20 - } + }// 21 Integer fieldIncrement() { return new Integer(this.count++);// 25 @@ -15,6 +15,7 @@ class TestCodeConstructs { class 'pkg/TestCodeConstructs' { method 'expressions ()V' { 7 6 + b 7 } method 'fieldIncrement ()Ljava/lang/Integer;' { @@ -26,4 +27,5 @@ class 'pkg/TestCodeConstructs' { Lines mapping: 20 <-> 7 +21 <-> 8 25 <-> 11 diff --git a/plugins/java-decompiler/engine/testData/results/TestConstants.dec b/plugins/java-decompiler/engine/testData/results/TestConstants.dec index 47f4c1d3a72b..28df2c294ca1 100644 --- a/plugins/java-decompiler/engine/testData/results/TestConstants.dec +++ b/plugins/java-decompiler/engine/testData/results/TestConstants.dec @@ -29,46 +29,99 @@ public class TestConstants { @TestConstants.A(byte.class) void m1() { - } + }// 54 @TestConstants.A(char.class) void m2() { - } + }// 55 @TestConstants.A(double.class) void m3() { - } + }// 56 @TestConstants.A(float.class) void m4() { - } + }// 57 @TestConstants.A(int.class) void m5() { - } + }// 58 @TestConstants.A(long.class) void m6() { - } + }// 59 @TestConstants.A(short.class) void m7() { - } + }// 60 @TestConstants.A(boolean.class) void m8() { - } + }// 61 @TestConstants.A(void.class) void m9() { - } + }// 62 @TestConstants.A(Date.class) void m10() { - } + }// 63 @interface A { Class value(); } } +class 'pkg/TestConstants' { + method 'm1 ()V' { + 0 31 + } + + method 'm2 ()V' { + 0 35 + } + + method 'm3 ()V' { + 0 39 + } + + method 'm4 ()V' { + 0 43 + } + + method 'm5 ()V' { + 0 47 + } + + method 'm6 ()V' { + 0 51 + } + + method 'm7 ()V' { + 0 55 + } + + method 'm8 ()V' { + 0 59 + } + + method 'm9 ()V' { + 0 63 + } + + method 'm10 ()V' { + 0 67 + } +} + +Lines mapping: +54 <-> 32 +55 <-> 36 +56 <-> 40 +57 <-> 44 +58 <-> 48 +59 <-> 52 +60 <-> 56 +61 <-> 60 +62 <-> 64 +63 <-> 68 diff --git a/plugins/java-decompiler/engine/testData/results/TestDeprecations.dec b/plugins/java-decompiler/engine/testData/results/TestDeprecations.dec index e423854d729a..077bdd7040cb 100644 --- a/plugins/java-decompiler/engine/testData/results/TestDeprecations.dec +++ b/plugins/java-decompiler/engine/testData/results/TestDeprecations.dec @@ -10,7 +10,7 @@ public abstract class TestDeprecations { /** @deprecated */ public void byComment() { boolean var1 = true;// 27 - } + }// 28 /** @deprecated */ public abstract void byCommentAbstract(); @@ -19,7 +19,7 @@ public abstract class TestDeprecations { @Deprecated public void byAnno() { boolean var1 = true;// 35 - } + }// 36 /** @deprecated */ @Deprecated @@ -32,7 +32,7 @@ public abstract class TestDeprecations { void foo() { boolean var1 = true;// 55 - } + }// 56 } /** @deprecated */ @@ -41,7 +41,7 @@ public abstract class TestDeprecations { void foo() { boolean var1 = true;// 46 - } + }// 47 } } @@ -49,11 +49,13 @@ class 'pkg/TestDeprecations' { method 'byComment ()V' { 0 11 1 11 + 2 12 } method 'byAnno ()V' { 0 20 1 20 + 2 21 } } @@ -61,6 +63,7 @@ class 'pkg/TestDeprecations$ByAnno' { method 'foo ()V' { 0 33 1 33 + 2 34 } } @@ -68,11 +71,16 @@ class 'pkg/TestDeprecations$ByComment' { method 'foo ()V' { 0 42 1 42 + 2 43 } } Lines mapping: 27 <-> 12 +28 <-> 13 35 <-> 21 +36 <-> 22 46 <-> 43 +47 <-> 44 55 <-> 34 +56 <-> 35 diff --git a/plugins/java-decompiler/engine/testData/results/TestEnum.dec b/plugins/java-decompiler/engine/testData/results/TestEnum.dec index e08f341a6065..06649c002abc 100644 --- a/plugins/java-decompiler/engine/testData/results/TestEnum.dec +++ b/plugins/java-decompiler/engine/testData/results/TestEnum.dec @@ -4,18 +4,18 @@ public enum TestEnum { E1, E2 { public void m() { - } + }// 22 }, E3("-"), E4("+") { public void m() { - } + }// 27 }; private String s; public void m() { - } + }// 30 private TestEnum() { this("?");// 34 @@ -26,17 +26,38 @@ public enum TestEnum { } } +class 'pkg/TestEnum$1' { + method 'm ()V' { + 0 6 + } +} + +class 'pkg/TestEnum$2' { + method 'm ()V' { + 0 11 + } +} + class 'pkg/TestEnum' { + method 'm ()V' { + 0 17 + } + method ' (Ljava/lang/String;I)V' { 3 20 5 20 + 8 21 } method ' (Ljava/lang/String;ILjava/lang/String;)V' { 8 24 + b 25 } } Lines mapping: +22 <-> 7 +27 <-> 12 +30 <-> 18 34 <-> 21 35 <-> 25 diff --git a/plugins/java-decompiler/engine/testData/results/TestInnerClassConstructor.dec b/plugins/java-decompiler/engine/testData/results/TestInnerClassConstructor.dec index 3db62038d2f6..235d50f44294 100644 --- a/plugins/java-decompiler/engine/testData/results/TestInnerClassConstructor.dec +++ b/plugins/java-decompiler/engine/testData/results/TestInnerClassConstructor.dec @@ -3,22 +3,23 @@ package pkg; class TestInnerClassConstructor { void m() { new TestInnerClassConstructor.Inner("text");// 5 - } + }// 6 void n(String var1) { System.out.println("n(): " + var1);// 9 - } + }// 10 final class Inner { private Inner(String var2) { TestInnerClassConstructor.this.n(var2);// 14 - } + }// 15 } } class 'pkg/TestInnerClassConstructor' { method 'm ()V' { 5 4 + c 5 } method 'n (Ljava/lang/String;)V' { @@ -26,16 +27,23 @@ class 'pkg/TestInnerClassConstructor' { a 8 13 8 16 8 + 19 9 } } class 'pkg/TestInnerClassConstructor$Inner' { method ' (Lpkg/TestInnerClassConstructor;Ljava/lang/String;)V' { b 13 + e 14 } } Lines mapping: 5 <-> 5 +6 <-> 6 9 <-> 9 +10 <-> 10 14 <-> 14 +15 <-> 15 +Not mapped: +13 diff --git a/plugins/java-decompiler/engine/testData/results/TestInnerLocal.dec b/plugins/java-decompiler/engine/testData/results/TestInnerLocal.dec index f9129fe8332c..6ca3a7e10530 100644 --- a/plugins/java-decompiler/engine/testData/results/TestInnerLocal.dec +++ b/plugins/java-decompiler/engine/testData/results/TestInnerLocal.dec @@ -5,13 +5,13 @@ public class TestInnerLocal { public Inner(String var1) { this.x = var1;// 22 - } + }// 23 } new Inner("test");// 25 new TestInnerLocal.Inner1Static("test");// 26 new TestInnerLocal.Inner1Static.Inner2Static("test");// 27 - } + }// 28 public void testMethod() { class Inner { @@ -19,28 +19,28 @@ public class TestInnerLocal { public Inner(String var2) { this.x = var2;// 34 - } + }// 35 } new Inner("test");// 37 new TestInnerLocal.Inner1Static("test");// 38 new TestInnerLocal.Inner1("test");// 39 new TestInnerLocal.Inner1Static.Inner2Static("test");// 40 - } + }// 41 static class Inner1Static { final String x; public Inner1Static(String var1) { this.x = var1;// 53 - } + }// 54 public static class Inner2Static { final String x; public Inner2Static(String var1) { this.x = var1;// 59 - } + }// 60 } } @@ -49,13 +49,14 @@ public class TestInnerLocal { public Inner1(String var2) { this.x = var2;// 46 - } + }// 47 } } class 'TestInnerLocal$1Inner' { method ' (Ljava/lang/String;)V' { 6 6 + 9 7 } } @@ -64,6 +65,7 @@ class 'TestInnerLocal' { 4 10 e 11 18 12 + 1e 13 } method 'testMethod ()V' { @@ -71,43 +73,61 @@ class 'TestInnerLocal' { f 25 1a 26 24 27 + 2a 28 } } class 'TestInnerLocal$2Inner' { method ' (LTestInnerLocal;Ljava/lang/String;)V' { b 20 + e 21 } } class 'TestInnerLocal$Inner1Static' { method ' (Ljava/lang/String;)V' { 6 34 + 9 35 } } class 'TestInnerLocal$Inner1Static$Inner2Static' { method ' (Ljava/lang/String;)V' { 6 41 + 9 42 } } class 'TestInnerLocal$Inner1' { method ' (LTestInnerLocal;Ljava/lang/String;)V' { b 50 + e 51 } } Lines mapping: 22 <-> 7 +23 <-> 8 25 <-> 11 26 <-> 12 27 <-> 13 +28 <-> 14 34 <-> 21 +35 <-> 22 37 <-> 25 38 <-> 26 39 <-> 27 40 <-> 28 +41 <-> 29 46 <-> 51 +47 <-> 52 53 <-> 35 +54 <-> 36 59 <-> 42 +60 <-> 43 +Not mapped: +21 +33 +45 +52 +58 diff --git a/plugins/java-decompiler/engine/testData/results/TestInnerLocalPkg.dec b/plugins/java-decompiler/engine/testData/results/TestInnerLocalPkg.dec index 5590d8ad37c7..7cafa415f9b6 100644 --- a/plugins/java-decompiler/engine/testData/results/TestInnerLocalPkg.dec +++ b/plugins/java-decompiler/engine/testData/results/TestInnerLocalPkg.dec @@ -7,13 +7,13 @@ public class TestInnerLocalPkg { public Inner(String var1) { this.x = var1;// 24 - } + }// 25 } new Inner("test");// 27 new TestInnerLocalPkg.Inner1Static("test");// 28 new TestInnerLocalPkg.Inner1Static.Inner2Static("test");// 29 - } + }// 30 public void testMethod() { class Inner { @@ -21,28 +21,28 @@ public class TestInnerLocalPkg { public Inner(String var2) { this.x = var2;// 36 - } + }// 37 } new Inner("test");// 39 new TestInnerLocalPkg.Inner1Static("test");// 40 new TestInnerLocalPkg.Inner1("test");// 41 new TestInnerLocalPkg.Inner1Static.Inner2Static("test");// 42 - } + }// 43 static class Inner1Static { final String x; public Inner1Static(String var1) { this.x = var1;// 55 - } + }// 56 public static class Inner2Static { final String x; public Inner2Static(String var1) { this.x = var1;// 61 - } + }// 62 } } @@ -51,13 +51,14 @@ public class TestInnerLocalPkg { public Inner1(String var2) { this.x = var2;// 48 - } + }// 49 } } class 'pkg/TestInnerLocalPkg$1Inner' { method ' (Ljava/lang/String;)V' { 6 8 + 9 9 } } @@ -66,6 +67,7 @@ class 'pkg/TestInnerLocalPkg' { 4 12 e 13 18 14 + 1e 15 } method 'testMethod ()V' { @@ -73,43 +75,61 @@ class 'pkg/TestInnerLocalPkg' { f 27 1a 28 24 29 + 2a 30 } } class 'pkg/TestInnerLocalPkg$2Inner' { method ' (Lpkg/TestInnerLocalPkg;Ljava/lang/String;)V' { b 22 + e 23 } } class 'pkg/TestInnerLocalPkg$Inner1Static' { method ' (Ljava/lang/String;)V' { 6 36 + 9 37 } } class 'pkg/TestInnerLocalPkg$Inner1Static$Inner2Static' { method ' (Ljava/lang/String;)V' { 6 43 + 9 44 } } class 'pkg/TestInnerLocalPkg$Inner1' { method ' (Lpkg/TestInnerLocalPkg;Ljava/lang/String;)V' { b 52 + e 53 } } Lines mapping: 24 <-> 9 +25 <-> 10 27 <-> 13 28 <-> 14 29 <-> 15 +30 <-> 16 36 <-> 23 +37 <-> 24 39 <-> 27 40 <-> 28 41 <-> 29 42 <-> 30 +43 <-> 31 48 <-> 53 +49 <-> 54 55 <-> 37 +56 <-> 38 61 <-> 44 +62 <-> 45 +Not mapped: +23 +35 +47 +54 +60 diff --git a/plugins/java-decompiler/engine/testData/results/TestInnerSignature.dec b/plugins/java-decompiler/engine/testData/results/TestInnerSignature.dec index e40a8327c3e3..3087a40dc632 100644 --- a/plugins/java-decompiler/engine/testData/results/TestInnerSignature.dec +++ b/plugins/java-decompiler/engine/testData/results/TestInnerSignature.dec @@ -7,7 +7,7 @@ public class TestInnerSignature { this.a = var1;// 23 this.b = var2;// 24 this.c = var3;// 25 - } + }// 26 public static class InnerStatic { A a; @@ -18,7 +18,7 @@ public class TestInnerSignature { this.a = var1;// 46 this.b = var2;// 47 this.c = var3;// 48 - } + }// 49 } public class Inner { @@ -30,7 +30,7 @@ public class TestInnerSignature { this.a = var2;// 34 this.b = var3;// 35 this.c = var4;// 36 - } + }// 37 } } @@ -39,6 +39,7 @@ class 'TestInnerSignature' { 6 6 b 7 10 8 + 13 9 } } @@ -47,6 +48,7 @@ class 'TestInnerSignature$InnerStatic' { 6 17 b 18 10 19 + 13 20 } } @@ -55,6 +57,7 @@ class 'TestInnerSignature$Inner' { b 29 10 30 16 31 + 19 32 } } @@ -62,9 +65,16 @@ Lines mapping: 23 <-> 7 24 <-> 8 25 <-> 9 +26 <-> 10 34 <-> 30 35 <-> 31 36 <-> 32 +37 <-> 33 46 <-> 18 47 <-> 19 48 <-> 20 +49 <-> 21 +Not mapped: +22 +33 +45 diff --git a/plugins/java-decompiler/engine/testData/results/TestLocalClass.dec b/plugins/java-decompiler/engine/testData/results/TestLocalClass.dec index 8e511673bb18..27c2958512f6 100644 --- a/plugins/java-decompiler/engine/testData/results/TestLocalClass.dec +++ b/plugins/java-decompiler/engine/testData/results/TestLocalClass.dec @@ -7,20 +7,20 @@ public abstract class TestLocalClass { void foo() { boolean var1 = true;// 11 boolean var2 = true;// 12 - } + }// 13 } Local var2 = new Local();// 15 var2.foo();// 16 - } + }// 17 void boo() { boolean var1 = true;// 20 - } + }// 21 void zoo() { boolean var1 = true;// 24 - } + }// 25 } class 'pkg/TestLocalClass$1Local' { @@ -29,6 +29,7 @@ class 'pkg/TestLocalClass$1Local' { 1 7 2 8 3 8 + 4 9 } } @@ -38,16 +39,19 @@ class 'pkg/TestLocalClass' { 1 4 a 12 c 13 + f 14 } method 'boo ()V' { 0 17 1 17 + 2 18 } method 'zoo ()V' { 0 21 1 21 + 2 22 } } @@ -55,7 +59,11 @@ Lines mapping: 8 <-> 5 11 <-> 8 12 <-> 9 +13 <-> 10 15 <-> 13 16 <-> 14 +17 <-> 15 20 <-> 18 +21 <-> 19 24 <-> 22 +25 <-> 23 diff --git a/plugins/java-decompiler/engine/testData/results/TestMethodParameters.dec b/plugins/java-decompiler/engine/testData/results/TestMethodParameters.dec index a45819211428..21f0f129d1bc 100644 --- a/plugins/java-decompiler/engine/testData/results/TestMethodParameters.dec +++ b/plugins/java-decompiler/engine/testData/results/TestMethodParameters.dec @@ -2,42 +2,106 @@ package pkg; public class TestMethodParameters { TestMethodParameters(@Deprecated int var1) { - } + }// 19 void m1(@Deprecated int var1) { - } + }// 20 static void m2(@Deprecated int var0) { - } + }// 21 void local() { class Local { Local(@Deprecated int var2) { - } + }// 36 void m(@Deprecated int var1) { - } + }// 37 } - } + }// 39 static class C2 { C2(@Deprecated int var1) { - } + }// 29 void m1(@Deprecated int var1) { - } + }// 30 static void m2(@Deprecated int var0) { - } + }// 31 } class C1 { C1(@Deprecated int var2) { - } + }// 24 void m(@Deprecated int var1) { - } + }// 25 } } +class 'pkg/TestMethodParameters' { + method ' (I)V' { + 4 4 + } + + method 'm1 (I)V' { + 0 7 + } + + method 'm2 (I)V' { + 0 10 + } + + method 'local ()V' { + 0 21 + } +} + +class 'pkg/TestMethodParameters$1Local' { + method ' (Lpkg/TestMethodParameters;I)V' { + 9 15 + } + + method 'm (I)V' { + 0 18 + } +} + +class 'pkg/TestMethodParameters$C2' { + method ' (I)V' { + 4 25 + } + + method 'm1 (I)V' { + 0 28 + } + + method 'm2 (I)V' { + 0 31 + } +} + +class 'pkg/TestMethodParameters$C1' { + method ' (Lpkg/TestMethodParameters;I)V' { + 9 36 + } + + method 'm (I)V' { + 0 39 + } +} + +Lines mapping: +19 <-> 5 +20 <-> 8 +21 <-> 11 +24 <-> 37 +25 <-> 40 +29 <-> 26 +30 <-> 29 +31 <-> 32 +36 <-> 16 +37 <-> 19 +39 <-> 22 diff --git a/plugins/java-decompiler/engine/testData/results/TestSynchronizedMapping.dec b/plugins/java-decompiler/engine/testData/results/TestSynchronizedMapping.dec index 6ba9f3352815..82b553b2bfdf 100644 --- a/plugins/java-decompiler/engine/testData/results/TestSynchronizedMapping.dec +++ b/plugins/java-decompiler/engine/testData/results/TestSynchronizedMapping.dec @@ -9,7 +9,7 @@ public class TestSynchronizedMapping { public void test2(String var1) { System.out.println(var1);// 14 - } + }// 15 } class 'pkg/TestSynchronizedMapping' { @@ -22,6 +22,7 @@ class 'pkg/TestSynchronizedMapping' { method 'test2 (Ljava/lang/String;)V' { 0 10 4 10 + 7 11 } } @@ -29,3 +30,6 @@ Lines mapping: 8 <-> 5 9 <-> 6 14 <-> 11 +15 <-> 12 +Not mapped: +10 diff --git a/plugins/java-decompiler/engine/testData/results/TestThrowException.dec b/plugins/java-decompiler/engine/testData/results/TestThrowException.dec index 7bc460e5f519..eae0e70a50ab 100644 --- a/plugins/java-decompiler/engine/testData/results/TestThrowException.dec +++ b/plugins/java-decompiler/engine/testData/results/TestThrowException.dec @@ -10,16 +10,17 @@ public class TestThrowException { this.r = new Runnable() {// 12 public void run() { boolean var1 = true;// 15 - } + }// 16 }; } - } + }// 18 } class 'pkg/TestThrowException$1' { method 'run ()V' { 0 11 1 11 + 2 12 } } @@ -29,6 +30,7 @@ class 'pkg/TestThrowException' { c 7 11 7 1b 9 + 1e 15 } } @@ -37,3 +39,7 @@ Lines mapping: 10 <-> 8 12 <-> 10 15 <-> 12 +16 <-> 13 +18 <-> 16 +Not mapped: +8 diff --git a/plugins/java-decompiler/engine/testData/results/TestTryCatchFinally.dec b/plugins/java-decompiler/engine/testData/results/TestTryCatchFinally.dec index 2dc71a58633f..cb596195a330 100644 --- a/plugins/java-decompiler/engine/testData/results/TestTryCatchFinally.dec +++ b/plugins/java-decompiler/engine/testData/results/TestTryCatchFinally.dec @@ -14,7 +14,7 @@ public class TestTryCatchFinally { System.out.println("finally");// 34 } - } + }// 36 int foo(int var1) throws Exception { if(var1 < 1) {// 39 @@ -36,7 +36,7 @@ public class TestTryCatchFinally { System.out.println("Finally");// 55 } - return -1; + return -1;// 56 } } @@ -51,6 +51,7 @@ class 'pkg/TestTryCatchFinally' { 2b 13 2d 13 30 13 + 38 16 } method 'foo (I)I' { @@ -66,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 } } @@ -80,6 +84,7 @@ Lines mapping: 24 <-> 6 27 <-> 9 34 <-> 14 +36 <-> 17 39 <-> 20 40 <-> 21 41 <-> 22 @@ -88,3 +93,11 @@ Lines mapping: 51 <-> 31 53 <-> 34 55 <-> 36 +56 <-> 39 +57 <-> 39 +Not mapped: +25 +28 +32 +35 +52 diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleImpl.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleImpl.java index 0f20db983c0c..6cadb53d5b91 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleImpl.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleImpl.java @@ -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; diff --git a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java index 626961e8b9f2..318b12048825 100644 --- a/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java +++ b/plugins/properties/properties-psi-impl/src/com/intellij/lang/properties/ResourceBundleManager.java @@ -215,6 +215,9 @@ public class ResourceBundleManager implements PersistentStateComponent{ 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(); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java index 4770ea7beb25..edc1bf93fc20 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java @@ -535,7 +535,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp return new RepeatSvnActionThroughBusy() { @Override protected void executeImpl() throws VcsException { - vcs.getFactory(file).createRevertClient().revert(new File[]{file}, Depth.allOrFiles(recursive), null); + vcs.getFactory(file).createRevertClient().revert(Collections.singletonList(file), Depth.allOrFiles(recursive), null); } }; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java index 3751c78b365e..4f38dcc7b8e3 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/BaseSvnClient.java @@ -99,16 +99,31 @@ public abstract class BaseSvnClient implements SvnClient { @NotNull SvnCommandName name, @NotNull List parameters, @Nullable LineCommandListener listener) throws SvnBindException { - Command command = new Command(name); + Command command = newCommand(name); + command.put(parameters); + + return execute(vcs, target, workingDirectory, command, listener); + } + + @NotNull + public CommandExecutor execute(@NotNull SvnVcs vcs, + @NotNull SvnTarget target, + @Nullable File workingDirectory, + @NotNull Command command, + @Nullable LineCommandListener listener) throws SvnBindException { command.setTarget(target); command.setWorkingDirectory(workingDirectory); command.setResultBuilder(listener); - command.put(parameters); return newRuntime(vcs).runWithAuthenticationAttempt(command); } + @NotNull + public Command newCommand(@NotNull SvnCommandName name) { + return new Command(name); + } + @NotNull public CommandRuntime newRuntime(@NotNull SvnVcs vcs) { return new CommandRuntime(vcs, new AuthenticationService(vcs, myIsActive)); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CheckinClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CheckinClient.java index cc8e2ef0e352..f7d5fcfbfaf1 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CheckinClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CheckinClient.java @@ -20,7 +20,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.idea.svn.api.SvnClient; import java.io.File; -import java.util.Collection; +import java.util.List; /** * @author Konstantin Kolosovsky. @@ -28,5 +28,5 @@ import java.util.Collection; public interface CheckinClient extends SvnClient { @NotNull - CommitInfo[] commit(@NotNull Collection paths, @NotNull String comment) throws VcsException; + CommitInfo[] commit(@NotNull List paths, @NotNull String comment) throws VcsException; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdCheckinClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdCheckinClient.java index ced5e62b0f33..50bd222e98c3 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdCheckinClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/CmdCheckinClient.java @@ -23,24 +23,22 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vcs.AbstractFilterChildren; import com.intellij.openapi.vcs.VcsException; -import com.intellij.util.ArrayUtil; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.SvnUtil; import org.jetbrains.idea.svn.api.BaseSvnClient; import org.jetbrains.idea.svn.api.Depth; -import org.jetbrains.idea.svn.commandLine.CommandUtil; -import org.jetbrains.idea.svn.commandLine.LineCommandAdapter; -import org.jetbrains.idea.svn.commandLine.SvnBindException; -import org.jetbrains.idea.svn.commandLine.SvnCommandName; +import org.jetbrains.idea.svn.commandLine.*; import org.jetbrains.idea.svn.status.Status; import org.jetbrains.idea.svn.status.StatusClient; import org.jetbrains.idea.svn.status.StatusType; import org.tmatesoft.svn.core.wc2.SvnTarget; import java.io.File; -import java.util.*; +import java.util.Collections; +import java.util.List; +import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -58,35 +56,31 @@ public class CmdCheckinClient extends BaseSvnClient implements CheckinClient { @NotNull @Override - public CommitInfo[] commit(@NotNull Collection paths, @NotNull String message) throws VcsException { + public CommitInfo[] commit(@NotNull List paths, @NotNull String message) throws VcsException { // if directory renames were used, IDEA reports all files under them as moved, but for svn we can not pass some of them // to commit command - since not all paths are registered as changes -> so we need to filter these cases, but only if // there at least some child-parent relationships in passed paths paths = filterCommittables(paths); - return commit(ArrayUtil.toObjectArray(paths, File.class), message); + return runCommit(paths, message); } @NotNull - public CommitInfo[] commit(@NotNull File[] paths, @NotNull String message) throws VcsException { - if (paths.length == 0) return new CommitInfo[]{CommitInfo.EMPTY}; + private CommitInfo[] runCommit(@NotNull List paths, @NotNull String message) throws VcsException { + if (ContainerUtil.isEmpty(paths)) return new CommitInfo[]{CommitInfo.EMPTY}; - final List parameters = new ArrayList(); - CommandUtil.put(parameters, Depth.EMPTY); - CommandUtil.put(parameters, false, "--no-unlock"); - CommandUtil.put(parameters, false, "--keep-changelists"); - CommandUtil.putChangeLists(parameters, null); + Command command = newCommand(SvnCommandName.ci); - parameters.add("-m"); - parameters.add(message); + command.put(Depth.EMPTY); + command.put("-m", message); // TODO: seems that sort is not necessary here - Arrays.sort(paths); - CommandUtil.put(parameters, paths); + ContainerUtil.sort(paths); + command.setTargets(paths); IdeaCommitHandler handler = new IdeaCommitHandler(ProgressManager.getInstance().getProgressIndicator()); CmdCheckinClient.CommandListener listener = new CommandListener(handler); - listener.setBaseDirectory(CommandUtil.correctUpToExistingParent(paths[0])); - execute(myVcs, SvnTarget.fromFile(paths[0]), SvnCommandName.ci, parameters, listener); + listener.setBaseDirectory(CommandUtil.correctUpToExistingParent(paths.get(0))); + execute(myVcs, SvnTarget.fromFile(paths.get(0)), null, command, listener); listener.throwExceptionIfOccurred(); long revision = validateRevisionNumber(listener.getCommittedRevision()); @@ -102,7 +96,8 @@ public class CmdCheckinClient extends BaseSvnClient implements CheckinClient { return revision; } - private Collection filterCommittables(@NotNull Collection committables) throws SvnBindException { + @NotNull + private List filterCommittables(@NotNull List committables) throws SvnBindException { final Set childrenOfSomebody = ContainerUtil.newHashSet(); new AbstractFilterChildren() { @Override diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnKitCheckinClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnKitCheckinClient.java index c3f203a9e02f..62e69cd5865c 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnKitCheckinClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/checkin/SvnKitCheckinClient.java @@ -32,7 +32,7 @@ import org.tmatesoft.svn.core.wc.SVNCommitClient; import org.tmatesoft.svn.core.wc.SVNCommitPacket; import java.io.File; -import java.util.Collection; +import java.util.List; /** * @author Konstantin Kolosovsky. @@ -43,7 +43,7 @@ public class SvnKitCheckinClient extends BaseSvnClient implements CheckinClient @NotNull @Override - public CommitInfo[] commit(@NotNull Collection paths, @NotNull String comment) throws VcsException { + public CommitInfo[] commit(@NotNull List paths, @NotNull String comment) throws VcsException { File[] pathsToCommit = ArrayUtil.toObjectArray(paths, File.class); boolean keepLocks = myVcs.getSvnConfiguration().isKeepLocks(); SVNCommitPacket[] commitPackets = null; diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/Command.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/Command.java index a20e2db48495..9edd8906fa77 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/Command.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/Command.java @@ -1,10 +1,12 @@ package org.jetbrains.idea.svn.commandLine; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.idea.svn.api.Depth; import org.jetbrains.idea.svn.api.ProgressTracker; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.wc.SVNRevision; @@ -13,6 +15,7 @@ import org.tmatesoft.svn.core.wc2.SvnTarget; import java.io.File; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.List; /** @@ -30,6 +33,7 @@ public class Command { @Nullable private LineCommandListener myResultBuilder; @Nullable private volatile SVNURL myRepositoryUrl; @NotNull private SvnTarget myTarget; + @Nullable private Collection myTargets; @Nullable private ProgressTracker myCanceller; @@ -37,6 +41,10 @@ public class Command { myName = name; } + public void put(@Nullable Depth depth) { + CommandUtil.put(myParameters, depth, false); + } + public void put(@NonNls @NotNull String... parameters) { put(Arrays.asList(parameters)); } @@ -92,6 +100,16 @@ public class Command { return myTarget; } + @Nullable + public List getTargetsPaths() { + return ContainerUtil.isEmpty(myTargets) ? null : ContainerUtil.map(myTargets, new Function() { + @Override + public String fun(File file) { + return file.getAbsolutePath(); + } + }); + } + @NotNull public SvnCommandName getName() { return myName; @@ -117,6 +135,10 @@ public class Command { myTarget = target; } + public void setTargets(@Nullable Collection targets) { + myTargets = targets; + } + // TODO: used only to ensure authentication info is not logged to file. Remove when command execution model is refactored // TODO: - so we could determine if parameter should be logged by the parameter itself. public void saveOriginalParameters() { @@ -139,6 +161,11 @@ public class Command { data.add(myName.getName()); data.addAll(myOriginalParameters); + List targetsPaths = getTargetsPaths(); + if (!ContainerUtil.isEmpty(targetsPaths)) { + data.addAll(targetsPaths); + } + return StringUtil.join(data, " "); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java index 97c5f9c00ed2..88c896f60c98 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java @@ -26,6 +26,9 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.util.EventDispatcher; +import com.intellij.util.SystemProperties; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.vcsUtil.VcsFileUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -51,11 +54,11 @@ public class CommandExecutor { private final AtomicReference myExitCodeReference; @Nullable private String myMessage; - @Nullable private File myMessageFile; private boolean myIsDestroyed; private boolean myNeedsDestroy; private volatile String myDestroyReason; private volatile boolean myWasCancelled; + @NotNull private final List myTempFiles; @NotNull protected final GeneralCommandLine myCommandLine; @NotNull protected final String myLocale; protected Process myProcess; @@ -81,6 +84,7 @@ public class CommandExecutor { myListeners.addListener(new CommandCancelTracker()); } myLock = new Object(); + myTempFiles = ContainerUtil.newArrayList(); myCommandLine = createCommandLine(); myCommandLine.setExePath(exePath); myCommandLine.setWorkDirectory(command.getWorkingDirectory()); @@ -149,13 +153,14 @@ public class CommandExecutor { } protected void cleanup() { - cleanupMessageFile(); + deleteTempFiles(); } protected void beforeCreateProcess() throws SvnBindException { EncodingEnvironmentUtil.fixDefaultEncodingIfMac(myCommandLine, null); setupLocale(); ensureMessageFile(); + ensureTargetsAdded(); } private void setupLocale() { @@ -167,22 +172,53 @@ public class CommandExecutor { } } + @NotNull + private File ensureCommandFile(@NotNull String prefix, + @NotNull String extension, + @NotNull String data, + @NotNull String parameterName) throws SvnBindException { + File result = createTempFile(prefix, extension); + myTempFiles.add(result); + + try { + FileUtil.writeToFile(result, data); + } + catch (IOException e) { + throw new SvnBindException(e); + } + + myCommandLine.addParameters(parameterName, result.getAbsolutePath()); + + return result; + } + private void ensureMessageFile() throws SvnBindException { if (myMessage != null) { - myMessageFile = createTempFile("commit-message", ".txt"); - try { - FileUtil.writeToFile(myMessageFile, myMessage); - } - catch (IOException e) { - throw new SvnBindException(e); - } - myCommandLine.addParameters("-F", myMessageFile.getAbsolutePath()); + ensureCommandFile("commit-message", ".txt", myMessage, "-F"); + myCommandLine.addParameters("--config-option", "config:miscellany:log-encoding=" + CharsetToolkit.UTF8); } } - private void cleanupMessageFile() { - deleteTempFile(myMessageFile); + private void ensureTargetsAdded() throws SvnBindException { + List targetsPaths = myCommand.getTargetsPaths(); + + if (!ContainerUtil.isEmpty(targetsPaths)) { + String targetsValue = StringUtil.join(targetsPaths, SystemProperties.getLineSeparator()); + + if (myCommandLine.getCommandLineString().length() + targetsValue.length() > VcsFileUtil.FILE_PATH_LIMIT) { + ensureCommandFile("command-targets", ".txt", targetsValue, "--targets"); + } + else { + myCommandLine.addParameters(targetsPaths); + } + } + } + + private void deleteTempFiles() { + for (File file : myTempFiles) { + deleteTempFile(file); + } } @NotNull diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java index 733d180b90b2..2635dfb7fa9e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandUtil.java @@ -84,12 +84,6 @@ public class CommandUtil { } } - public static void put(@NotNull List parameters, @NotNull File... paths) { - for (File path : paths) { - put(parameters, path); - } - } - public static void put(@NotNull List parameters, @Nullable Depth depth) { put(parameters, depth, false); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ToBeMergedDialog.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ToBeMergedDialog.java index 7eb3b62c3ddc..d1ec9715ae45 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ToBeMergedDialog.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/integrate/ToBeMergedDialog.java @@ -265,7 +265,7 @@ public class ToBeMergedDialog extends DialogWrapper implements MergeDialogI { final List svnChangeLists = ContainerUtil.findAll(changeLists, SvnChangeList.class); for (SvnChangeList svnChangeList : svnChangeLists) { - final Collection notMerged = myMergeChecker.getNotMergedPaths(svnChangeList.getNumber()); + final Collection notMerged = myMergeChecker.getNotMergedPaths(svnChangeList); if (!ContainerUtil.isEmpty(notMerged)) { for (String path : svnChangeList.getAffectedPaths()) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/MergeChecker.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/MergeChecker.java index e8fc08f4c7d0..6e6e66571c8c 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/MergeChecker.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/MergeChecker.java @@ -1,12 +1,20 @@ package org.jetbrains.idea.svn.mergeinfo; +import com.intellij.openapi.vcs.VcsException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.history.SvnChangeList; import java.util.Collection; public interface MergeChecker { - SvnMergeInfoCache.MergeCheckResult checkList(SvnChangeList list); + + void prepare() throws VcsException; + + @NotNull + SvnMergeInfoCache.MergeCheckResult checkList(@NotNull SvnChangeList changeList); // if nothing, maybe all not merged or merged: here only partly not merged - Collection getNotMergedPaths(long number); + @Nullable + Collection getNotMergedPaths(@NotNull SvnChangeList changeList); } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneShotMergeInfoHelper.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneShotMergeInfoHelper.java index bdd13c820acb..aa42733c4ed5 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneShotMergeInfoHelper.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/mergeinfo/OneShotMergeInfoHelper.java @@ -64,6 +64,7 @@ public class OneShotMergeInfoHelper implements MergeChecker { }); } + @Override public void prepare() throws VcsException { Depth depth = Depth.allOrEmpty(myMergeContext.getVcs().getSvnConfiguration().isCheckNestedForQuickMerge()); File file = myMergeContext.getWcInfo().getRootInfo().getIoFile(); @@ -73,8 +74,8 @@ public class OneShotMergeInfoHelper implements MergeChecker { } @Nullable - public Collection getNotMergedPaths(long number) { - return myPartiallyMerged.get(number); + public Collection getNotMergedPaths(@NotNull SvnChangeList changeList) { + return myPartiallyMerged.get(changeList.getNumber()); } @NotNull diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/CmdRevertClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/CmdRevertClient.java index a57e24b525d7..1993de3fa77a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/CmdRevertClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/CmdRevertClient.java @@ -1,19 +1,20 @@ package org.jetbrains.idea.svn.revert; import com.intellij.openapi.vcs.VcsException; +import com.intellij.util.ObjectUtils; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.Convertor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.*; +import org.jetbrains.idea.svn.commandLine.Command; import org.jetbrains.idea.svn.commandLine.CommandExecutor; import org.jetbrains.idea.svn.commandLine.CommandUtil; import org.jetbrains.idea.svn.commandLine.SvnCommandName; -import org.jetbrains.idea.svn.api.Depth; import org.tmatesoft.svn.core.wc2.SvnTarget; import java.io.File; -import java.util.ArrayList; -import java.util.List; +import java.util.Collection; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -28,29 +29,23 @@ public class CmdRevertClient extends BaseSvnClient implements RevertClient { private static final Pattern CHANGED_PATH = Pattern.compile(STATUS + PATH + OPTIONAL_COMMENT); @Override - public void revert(@NotNull File[] paths, @Nullable Depth depth, @Nullable ProgressTracker handler) throws VcsException { - if (paths.length > 0) { - List parameters = prepareParameters(paths, depth); + public void revert(@NotNull Collection paths, @Nullable Depth depth, @Nullable ProgressTracker handler) throws VcsException { + if (!ContainerUtil.isEmpty(paths)) { + Command command = newCommand(SvnCommandName.revert); + + command.put(depth); + command.setTargets(paths); // TODO: handler should be called in parallel with command execution, but this will be in other thread // TODO: check if that is ok for current handler implementation // TODO: add possibility to invoke "handler.checkCancelled" - process should be killed - CommandExecutor command = - execute(myVcs, SvnTarget.fromFile(paths[0]), CommandUtil.getHomeDirectory(), SvnCommandName.revert, parameters, null); + SvnTarget target = SvnTarget.fromFile(ObjectUtils.assertNotNull(ContainerUtil.getFirstItem(paths))); + CommandExecutor executor = execute(myVcs, target, CommandUtil.getHomeDirectory(), command, null); FileStatusResultParser parser = new FileStatusResultParser(CHANGED_PATH, handler, new RevertStatusConvertor()); - parser.parse(command.getOutput()); + parser.parse(executor.getOutput()); } } - private static List prepareParameters(File[] paths, Depth depth) { - ArrayList parameters = new ArrayList(); - - CommandUtil.put(parameters, paths); - CommandUtil.put(parameters, depth); - - return parameters; - } - private static class RevertStatusConvertor implements Convertor { public ProgressEvent convert(@NotNull Matcher matcher) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/RevertClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/RevertClient.java index 5f0d26bb09aa..5866ede7939e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/RevertClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/RevertClient.java @@ -8,11 +8,12 @@ import org.jetbrains.idea.svn.api.ProgressTracker; import org.jetbrains.idea.svn.api.SvnClient; import java.io.File; +import java.util.Collection; /** * @author Konstantin Kolosovsky. */ public interface RevertClient extends SvnClient { - void revert(@NotNull File[] paths, @Nullable Depth depth, @Nullable ProgressTracker handler) throws VcsException; + void revert(@NotNull Collection paths, @Nullable Depth depth, @Nullable ProgressTracker handler) throws VcsException; } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/SvnKitRevertClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/SvnKitRevertClient.java index 06593f472106..8dca2c72b2e1 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/SvnKitRevertClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/revert/SvnKitRevertClient.java @@ -1,6 +1,7 @@ package org.jetbrains.idea.svn.revert; import com.intellij.openapi.vcs.VcsException; +import com.intellij.util.ArrayUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.idea.svn.api.BaseSvnClient; @@ -10,6 +11,7 @@ import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.wc.SVNWCClient; import java.io.File; +import java.util.Collection; /** * @author Konstantin Kolosovsky. @@ -17,12 +19,12 @@ import java.io.File; public class SvnKitRevertClient extends BaseSvnClient implements RevertClient { @Override - public void revert(@NotNull File[] paths, @Nullable Depth depth, @Nullable ProgressTracker handler) throws VcsException { + public void revert(@NotNull Collection paths, @Nullable Depth depth, @Nullable ProgressTracker handler) throws VcsException { SVNWCClient client = myVcs.getSvnKitManager().createWCClient(); client.setEventHandler(toEventHandler(handler)); try { - client.doRevert(paths, toDepth(depth), null); + client.doRevert(ArrayUtil.toObjectArray(paths, File.class), toDepth(depth), null); } catch (SVNException e) { throw new VcsException(e); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/Reverter.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/Reverter.java index 2a6182e7a67f..2ee862c54327 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/Reverter.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/Reverter.java @@ -19,7 +19,6 @@ import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vcs.FilePathImpl; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.rollback.RollbackProgressListener; -import com.intellij.util.ArrayUtil; import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; @@ -67,8 +66,7 @@ public class Reverter { File target = files.iterator().next(); try { // Files passed here are split into groups by root and working copy format - thus we could determine factory based on first file - myVcs.getFactory(target).createRevertClient() - .revert(ArrayUtil.toObjectArray(files, File.class), Depth.allOrEmpty(recursive), myHandler); + myVcs.getFactory(target).createRevertClient().revert(files, Depth.allOrEmpty(recursive), myHandler); } catch (VcsException e) { processRevertError(e); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java index 355fc3fff6a0..ce9ce271ffa6 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/rollback/SvnRollbackEnvironment.java @@ -33,6 +33,7 @@ import org.tmatesoft.svn.core.wc.SVNRevision; import java.io.File; import java.util.Collection; +import java.util.Collections; import java.util.List; /** @@ -124,7 +125,7 @@ public class SvnRollbackEnvironment extends DefaultRollbackEnvironment { } private void doRevert(@NotNull File path, boolean recursive) throws VcsException { - mySvnVcs.getFactory(path).createRevertClient().revert(new File[]{path}, Depth.allOrFiles(recursive), null); + mySvnVcs.getFactory(path).createRevertClient().revert(Collections.singletonList(path), Depth.allOrFiles(recursive), null); } private boolean is17OrGreaterCopy(@NotNull File file, @NotNull Info info) throws VcsException { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/MergeFromTheirsResolver.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/MergeFromTheirsResolver.java index b655cdca170c..46c283dcefdf 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/MergeFromTheirsResolver.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/MergeFromTheirsResolver.java @@ -178,7 +178,7 @@ public class MergeFromTheirsResolver { @Override public void run(ContinuationContext context) { try { - new SvnTreeConflictResolver(myVcs, myOldFilePath, myCommittedRevision, null).resolveSelectMineFull(myDescription); + new SvnTreeConflictResolver(myVcs, myOldFilePath, null).resolveSelectMineFull(); } catch (VcsException e1) { context.handleException(e1, false); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/SvnTreeConflictResolver.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/SvnTreeConflictResolver.java index 584666c7e86a..8f1f4b14c42e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/SvnTreeConflictResolver.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/SvnTreeConflictResolver.java @@ -21,24 +21,22 @@ import com.intellij.openapi.vcs.FilePath; import com.intellij.openapi.vcs.VcsException; import com.intellij.openapi.vcs.changes.ChangesUtil; import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager; -import com.intellij.openapi.vcs.history.VcsRevisionNumber; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.idea.svn.SvnRevisionNumber; import org.jetbrains.idea.svn.SvnVcs; import org.jetbrains.idea.svn.api.Depth; import org.jetbrains.idea.svn.commandLine.SvnBindException; -import org.jetbrains.idea.svn.conflict.TreeConflictDescription; import org.jetbrains.idea.svn.status.Status; import org.jetbrains.idea.svn.status.StatusClient; import org.jetbrains.idea.svn.status.StatusConsumer; import org.jetbrains.idea.svn.status.StatusType; import org.tmatesoft.svn.core.SVNException; -import org.tmatesoft.svn.core.wc.*; +import org.tmatesoft.svn.core.wc.SVNRevision; import java.io.File; -import java.util.HashSet; +import java.util.Collections; import java.util.Set; /** @@ -48,105 +46,116 @@ import java.util.Set; * Time: 1:03 PM */ public class SvnTreeConflictResolver { - private final SvnVcs myVcs; - private final FilePath myPath; - private VcsRevisionNumber myCommittedRevision; - private final FilePath myRevertPath; - private final VcsDirtyScopeManager myDirtyScopeManager; - public SvnTreeConflictResolver(SvnVcs vcs, FilePath path, VcsRevisionNumber committedRevision, final @Nullable FilePath revertPath) { + @NotNull private final SvnVcs myVcs; + @NotNull private final FilePath myPath; + @Nullable private final FilePath myRevertPath; + @NotNull private final VcsDirtyScopeManager myDirtyScopeManager; + + public SvnTreeConflictResolver(@NotNull SvnVcs vcs, @NotNull FilePath path, @Nullable FilePath revertPath) { myVcs = vcs; myPath = path; - myCommittedRevision = committedRevision; myRevertPath = revertPath; myDirtyScopeManager = VcsDirtyScopeManager.getInstance(myVcs.getProject()); } - public void resolveSelectTheirsFull(TreeConflictDescription d) throws VcsException { + public void resolveSelectTheirsFull() throws VcsException { final LocalHistory localHistory = LocalHistory.getInstance(); - localHistory.putSystemLabel(myVcs.getProject(), "Before accepting theirs for " + TreeConflictRefreshablePanel.filePath(myPath)); + String pathPresentation = TreeConflictRefreshablePanel.filePath(myPath); + + localHistory.putSystemLabel(myVcs.getProject(), "Before accepting theirs for " + pathPresentation); try { - updatetoTheirsFull(); + updateToTheirsFull(); pathDirty(myPath); revertAdditional(); } finally { - localHistory.putSystemLabel(myVcs.getProject(), "After accepting theirs for " + TreeConflictRefreshablePanel.filePath(myPath)); + localHistory.putSystemLabel(myVcs.getProject(), "After accepting theirs for " + pathPresentation); } } - private void pathDirty(final FilePath path) { - final VirtualFile validParent = ChangesUtil.findValidParentAccurately(path); - if (validParent == null) return; - validParent.refresh(false, true); - if (path.isDirectory()) { - myDirtyScopeManager.dirDirtyRecursively(path); - } - else { - myDirtyScopeManager.fileDirty(path); + private void pathDirty(@NotNull FilePath path) { + VirtualFile validParent = ChangesUtil.findValidParentAccurately(path); + + if (validParent != null) { + validParent.refresh(false, true); + + if (path.isDirectory()) { + myDirtyScopeManager.dirDirtyRecursively(path); + } + else { + myDirtyScopeManager.fileDirty(path); + } } } private void revertAdditional() throws VcsException { - if (myRevertPath == null) return; - final File ioFile = myRevertPath.getIOFile(); - final Status status = myVcs.getFactory(ioFile).createStatusClient().doStatus(ioFile, false); - myVcs.getFactory(ioFile).createRevertClient().revert(new File[]{ioFile}, Depth.INFINITY, null); - if (StatusType.STATUS_ADDED.equals(status.getNodeStatus())) { - FileUtil.delete(ioFile); + if (myRevertPath != null) { + final File ioFile = myRevertPath.getIOFile(); + final Status status = myVcs.getFactory(ioFile).createStatusClient().doStatus(ioFile, false); + + revert(ioFile); + if (StatusType.STATUS_ADDED.equals(status.getNodeStatus())) { + FileUtil.delete(ioFile); + } + pathDirty(myRevertPath); } - pathDirty(myRevertPath); } - public void resolveSelectMineFull(TreeConflictDescription d) throws VcsException { + public void resolveSelectMineFull() throws VcsException { final File ioFile = myPath.getIOFile(); myVcs.getFactory(ioFile).createConflictClient().resolve(ioFile, Depth.INFINITY, true, true, true); pathDirty(myPath); } - private void updatetoTheirsFull() throws VcsException { + private void updateToTheirsFull() throws VcsException { final File ioFile = myPath.getIOFile(); Status status = myVcs.getFactory(ioFile).createStatusClient().doStatus(ioFile, false); - if (myCommittedRevision == null) { - myCommittedRevision = new SvnRevisionNumber(status.getCommittedRevision()); - } + if (status == null || StatusType.STATUS_UNVERSIONED.equals(status.getNodeStatus())) { - myVcs.getFactory(ioFile).createRevertClient().revert(new File[]{ioFile}, Depth.INFINITY, null); - updateIoFile(ioFile, SVNRevision.HEAD); - return; + revert(ioFile); + updateFile(ioFile, SVNRevision.HEAD); } else if (StatusType.STATUS_ADDED.equals(status.getNodeStatus())) { - myVcs.getFactory(ioFile).createRevertClient().revert(new File[]{ioFile}, Depth.INFINITY, null); - updateIoFile(ioFile, SVNRevision.HEAD); + revert(ioFile); + updateFile(ioFile, SVNRevision.HEAD); FileUtil.delete(ioFile); - return; } else { - final Set usedToBeAdded = new HashSet(); - if (myPath.isDirectory()) { - StatusClient statusClient = myVcs.getFactory(ioFile).createStatusClient(); - statusClient.doStatus(ioFile, SVNRevision.UNDEFINED, Depth.INFINITY, false, false, false, false, - new StatusConsumer() { - @Override - public void consume(Status status) throws SVNException { - if (status != null && StatusType.STATUS_ADDED.equals(status.getNodeStatus())) { - usedToBeAdded.add(status.getFile()); - } - } - }, null); - } - myVcs.getFactory(ioFile).createRevertClient().revert(new File[]{ioFile}, Depth.INFINITY, null); + Set usedToBeAdded = myPath.isDirectory() ? getDescendantsWithAddedStatus(ioFile) : ContainerUtil.newHashSet(); + + revert(ioFile); for (File wasAdded : usedToBeAdded) { FileUtil.delete(wasAdded); } - updateIoFile(ioFile, SVNRevision.HEAD); + updateFile(ioFile, SVNRevision.HEAD); } } - private void updateIoFile(@NotNull File ioFile, @NotNull final SVNRevision revision) throws SvnBindException { - if (! ioFile.exists()) { - File parent = ioFile.getParentFile(); - myVcs.getFactory(parent).createUpdateClient().doUpdate(parent, revision, Depth.INFINITY, true, false); - } else { - myVcs.getFactory(ioFile).createUpdateClient().doUpdate(ioFile, revision, Depth.INFINITY, false, false); - } + @NotNull + private Set getDescendantsWithAddedStatus(@NotNull File ioFile) throws SvnBindException { + final Set result = ContainerUtil.newHashSet(); + StatusClient statusClient = myVcs.getFactory(ioFile).createStatusClient(); + + statusClient.doStatus(ioFile, SVNRevision.UNDEFINED, Depth.INFINITY, false, false, false, false, + new StatusConsumer() { + @Override + public void consume(Status status) throws SVNException { + if (status != null && StatusType.STATUS_ADDED.equals(status.getNodeStatus())) { + result.add(status.getFile()); + } + } + }, null); + + return result; + } + + private void revert(@NotNull File file) throws VcsException { + myVcs.getFactory(file).createRevertClient().revert(Collections.singletonList(file), Depth.INFINITY, null); + } + + private void updateFile(@NotNull File file, @NotNull SVNRevision revision) throws SvnBindException { + boolean useParentAsTarget = !file.exists(); + File target = useParentAsTarget ? file.getParentFile() : file; + + myVcs.getFactory(target).createUpdateClient().doUpdate(target, revision, Depth.INFINITY, useParentAsTarget, false); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/TreeConflictRefreshablePanel.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/TreeConflictRefreshablePanel.java index 05dd836be02a..5314daf15b2a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/TreeConflictRefreshablePanel.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/treeConflict/TreeConflictRefreshablePanel.java @@ -280,7 +280,7 @@ public class TreeConflictRefreshablePanel extends AbstractRefreshablePanel { true) { @Override protected void process(TreeConflictDescription d) throws VcsException { - new SvnTreeConflictResolver(myVcs, paths.myMainPath, myCommittedRevision, paths.myAdditionalPath).resolveSelectTheirsFull(d); + new SvnTreeConflictResolver(myVcs, paths.myMainPath, paths.myAdditionalPath).resolveSelectTheirsFull(); } @Override @@ -337,7 +337,7 @@ public class TreeConflictRefreshablePanel extends AbstractRefreshablePanel { true) { @Override protected void process(TreeConflictDescription d) throws VcsException { - new SvnTreeConflictResolver(myVcs, paths.myMainPath, myCommittedRevision, paths.myAdditionalPath).resolveSelectMineFull(d); + new SvnTreeConflictResolver(myVcs, paths.myMainPath, paths.myAdditionalPath).resolveSelectMineFull(); } @Override diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnResolveTreeAcceptVariantsTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnResolveTreeAcceptVariantsTest.java index 03d3875b37b2..7dd99a049f7c 100644 --- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnResolveTreeAcceptVariantsTest.java +++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnResolveTreeAcceptVariantsTest.java @@ -136,9 +136,9 @@ public class SvnResolveTreeAcceptVariantsTest extends Svn17TestCase { final SvnRevisionNumber committedRevision = change.getBeforeRevision() != null ? (SvnRevisionNumber)change.getBeforeRevision().getRevisionNumber() : null; //SvnRevisionNumber committedRevision = new SvnRevisionNumber(SVNRevision.create(cnt * 2 + 1)); - final SvnTreeConflictResolver resolver = new SvnTreeConflictResolver(myVcs, filePath, committedRevision, null); + final SvnTreeConflictResolver resolver = new SvnTreeConflictResolver(myVcs, filePath, null); - resolver.resolveSelectMineFull(((ConflictedSvnChange)change).getBeforeDescription()); + resolver.resolveSelectMineFull(); myTheirs.refresh(false, true); myWorkingCopyDir.refresh(false, true); @@ -250,9 +250,9 @@ public class SvnResolveTreeAcceptVariantsTest extends Svn17TestCase { beforePath = change.getBeforeRevision().getFile(); } //SvnRevisionNumber committedRevision = new SvnRevisionNumber(SVNRevision.create(cnt * 2 + 1)); - final SvnTreeConflictResolver resolver = new SvnTreeConflictResolver(myVcs, filePath, committedRevision, beforePath); + final SvnTreeConflictResolver resolver = new SvnTreeConflictResolver(myVcs, filePath, beforePath); - resolver.resolveSelectTheirsFull(((ConflictedSvnChange) change).getBeforeDescription()); + resolver.resolveSelectTheirsFull(); myTheirs.refresh(false, true); myWorkingCopyDir.refresh(false, true); diff --git a/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.java b/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.java index 0fdca7a46da5..7b3171506912 100644 --- a/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.java +++ b/plugins/tasks/tasks-api/src/com/intellij/tasks/config/BaseRepositoryEditor.java @@ -19,6 +19,7 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.editor.EditorFactory; +import com.intellij.openapi.editor.ex.EditorEx; import com.intellij.openapi.project.Project; import com.intellij.openapi.ui.Messages; import com.intellij.tasks.TaskManager; @@ -32,6 +33,7 @@ import com.intellij.ui.components.JBLabel; import com.intellij.ui.components.JBTabbedPane; import com.intellij.util.Consumer; import com.intellij.util.net.HttpConfigurable; +import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -117,6 +119,7 @@ public class BaseRepositoryEditor extends TaskReposito myAddCommitMessage.setSelected(repository.isShouldFormatCommitMessage()); myDocument = EditorFactory.getInstance().createDocument(repository.getCommitMessageFormat()); myEditor = EditorFactory.getInstance().createEditor(myDocument); + myEditor.getSettings().setCaretRowShown(false); myEditorPanel.add(myEditor.getComponent(), BorderLayout.CENTER); myComment.setText("Available placeholders: " + repository.getComment()); String advertiser = repository.getRepositoryType().getAdvertiser(); @@ -234,6 +237,9 @@ public class BaseRepositoryEditor extends TaskReposito try { myApplying = true; apply(); + boolean selected = myAddCommitMessage.isSelected(); + UIUtil.setEnabled(myEditorPanel, selected, true); + ((EditorEx)myEditor).setRendererMode(!selected); } finally { myApplying = false; diff --git a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRepository.java b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRepository.java index ec0e612f4e81..fc47b52b5ade 100644 --- a/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRepository.java +++ b/plugins/tasks/tasks-core/jira/src/com/intellij/tasks/jira/JiraRepository.java @@ -27,7 +27,7 @@ import com.intellij.tasks.LocalTask; import com.intellij.tasks.Task; import com.intellij.tasks.TaskBundle; import com.intellij.tasks.impl.BaseRepositoryImpl; -import com.intellij.tasks.impl.gson.GsonUtil; +import com.intellij.tasks.impl.gson.TaskGsonUtil; import com.intellij.tasks.jira.rest.JiraRestApi; import com.intellij.tasks.jira.soap.JiraLegacyApi; import com.intellij.util.ArrayUtil; @@ -54,7 +54,7 @@ import java.util.regex.Pattern; @Tag("JIRA") public class JiraRepository extends BaseRepositoryImpl { - public static final Gson GSON = GsonUtil.createDefaultBuilder().create(); + public static final Gson GSON = TaskGsonUtil.createDefaultBuilder().create(); private final static Logger LOG = Logger.getInstance(JiraRepository.class); public static final String REST_API_PATH = "/rest/api/latest"; diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java index 978967a5377d..d23eef822540 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/actions/OpenTaskDialog.java @@ -131,7 +131,7 @@ public class OpenTaskDialog extends DialogWrapper { } else { for (VcsTaskHandler handler : handlers) { - VcsTaskHandler.TaskInfo[] tasks = handler.getCurrentTasks(); + VcsTaskHandler.TaskInfo[] tasks = handler.getAllExistingTasks(); if (tasks.length > 0) { myVcsTaskHandler = handler; //noinspection unchecked diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/gitlab/GitlabRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/gitlab/GitlabRepository.java index 33d3d466e543..535e20a008d8 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/gitlab/GitlabRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/gitlab/GitlabRepository.java @@ -7,7 +7,7 @@ import com.intellij.tasks.Task; import com.intellij.tasks.TaskRepositoryType; import com.intellij.tasks.gitlab.model.GitlabIssue; import com.intellij.tasks.gitlab.model.GitlabProject; -import com.intellij.tasks.impl.gson.GsonUtil; +import com.intellij.tasks.impl.gson.TaskGsonUtil; import com.intellij.tasks.impl.httpclient.NewBaseRepositoryImpl; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; @@ -32,8 +32,8 @@ import java.util.Collections; import java.util.List; import java.util.regex.Pattern; -import static com.intellij.tasks.impl.httpclient.ResponseUtil.GsonMultipleObjectsDeserializer; -import static com.intellij.tasks.impl.httpclient.ResponseUtil.GsonSingleObjectDeserializer; +import static com.intellij.tasks.impl.httpclient.TaskResponseUtil.GsonMultipleObjectsDeserializer; +import static com.intellij.tasks.impl.httpclient.TaskResponseUtil.GsonSingleObjectDeserializer; /** * @author Mikhail Golubev @@ -44,7 +44,7 @@ public class GitlabRepository extends NewBaseRepositoryImpl { @NonNls public static final String REST_API_PATH_PREFIX = "/api/v3/"; private static final Pattern ID_PATTERN = Pattern.compile("\\d+"); - public static final Gson GSON = GsonUtil.createDefaultBuilder().create(); + public static final Gson GSON = TaskGsonUtil.createDefaultBuilder().create(); public static final TypeToken> LIST_OF_PROJECTS_TYPE = new TypeToken>() { }; public static final TypeToken> LIST_OF_ISSUES_TYPE = new TypeToken>() { diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUtil.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUtil.java index 32428edbf79b..29b1a01a209e 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUtil.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/TaskUtil.java @@ -27,15 +27,13 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.tasks.Task; import com.intellij.tasks.TaskRepository; -import com.intellij.tasks.TaskState; -import com.intellij.tasks.impl.httpclient.ResponseUtil; +import com.intellij.tasks.impl.httpclient.TaskResponseUtil; import com.intellij.util.text.DateFormatUtil; import org.apache.commons.httpclient.Header; import org.apache.commons.httpclient.HttpMethod; import org.apache.http.HttpResponse; import org.apache.http.protocol.HTTP; import org.jdom.Element; -import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -248,7 +246,7 @@ public class TaskUtil { public static void prettyFormatResponseToLog(@NotNull Logger logger, @NotNull HttpMethod response) { if (logger.isDebugEnabled() && response.hasBeenUsed()) { try { - String content = ResponseUtil.getResponseContentAsString(response); + String content = TaskResponseUtil.getResponseContentAsString(response); Header header = response.getRequestHeader(HTTP.CONTENT_TYPE); String contentType = header == null ? "text/plain" : header.getElements()[0].getName().toLowerCase(Locale.ENGLISH); if (contentType.contains("xml")) { @@ -270,7 +268,7 @@ public class TaskUtil { public static void prettyFormatResponseToLog(@NotNull Logger logger, @NotNull HttpResponse response) { if (logger.isDebugEnabled()) { try { - String content = ResponseUtil.getResponseContentAsString(response); + String content = TaskResponseUtil.getResponseContentAsString(response); org.apache.http.Header header = response.getEntity().getContentType(); String contentType = header == null ? "text/plain" : header.getElements()[0].getName().toLowerCase(Locale.ENGLISH); if (contentType.contains("xml")) { @@ -303,12 +301,4 @@ public class TaskUtil { throw new AssertionError("UTF-8 is not supported"); } } - - @Contract("null, _ -> false") - public static boolean isStateSupported(@Nullable TaskRepository repository, @NotNull TaskState state) { - if (repository == null || !repository.isSupported(TaskRepository.STATE_UPDATING)) { - return false; - } - return repository.getRepositoryType().getPossibleTaskStates().contains(state); - } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/gson/GsonUtil.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/gson/TaskGsonUtil.java similarity index 62% rename from plugins/tasks/tasks-core/src/com/intellij/tasks/impl/gson/GsonUtil.java rename to plugins/tasks/tasks-core/src/com/intellij/tasks/impl/gson/TaskGsonUtil.java index 8e3b80d5d9b5..330d9b793f38 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/gson/GsonUtil.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/gson/TaskGsonUtil.java @@ -9,10 +9,9 @@ import java.util.Date; /** * @author Mikhail Golubev */ -public class GsonUtil { +public class TaskGsonUtil { - private GsonUtil() { - // empty + private TaskGsonUtil() { } public static final JsonDeserializer DATE_DESERIALIZER = new JsonDeserializer() { @@ -24,12 +23,12 @@ public class GsonUtil { /** * Create default GsonBuilder used to create Gson factories across various task repository implementations. - * It uses {@link TaskUtil#formatDate(java.util.Date)} to parse dates and {@link NullCheckingFactory} + * It uses {@link TaskUtil#formatDate(Date)} to parse dates and {@link NullCheckingFactory} * to preserve null-safety of objects returned by server. * - * @see com.intellij.tasks.impl.gson.NullCheckingFactory - * @see com.intellij.tasks.impl.gson.Mandatory - * @see com.intellij.tasks.impl.gson.RestModel + * @see NullCheckingFactory + * @see Mandatory + * @see RestModel * @return described builder */ public static GsonBuilder createDefaultBuilder() { @@ -37,12 +36,4 @@ public class GsonUtil { .registerTypeAdapter(Date.class, DATE_DESERIALIZER) .registerTypeAdapterFactory(NullCheckingFactory.INSTANCE); } - - /** - * @deprecated use {@link #createDefaultBuilder} instead - */ - @Deprecated - public static GsonBuilder installDateDeserializer(GsonBuilder builder) { - return builder.registerTypeAdapter(Date.class, DATE_DESERIALIZER); - } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/httpclient/ResponseUtil.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/httpclient/TaskResponseUtil.java similarity index 95% rename from plugins/tasks/tasks-core/src/com/intellij/tasks/impl/httpclient/ResponseUtil.java rename to plugins/tasks/tasks-core/src/com/intellij/tasks/impl/httpclient/TaskResponseUtil.java index c3fc81ec27e7..c5e1095028da 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/httpclient/ResponseUtil.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/impl/httpclient/TaskResponseUtil.java @@ -46,8 +46,8 @@ import java.util.List; /** * @author Mikhail Golubev */ -public class ResponseUtil { - public static final Logger LOG = Logger.getInstance(ResponseUtil.class); +public class TaskResponseUtil { + public static final Logger LOG = Logger.getInstance(TaskResponseUtil.class); public static final String DEFAULT_CHARSET_NAME = CharsetToolkit.UTF8; public final static Charset DEFAULT_CHARSET = Charset.forName(DEFAULT_CHARSET_NAME); @@ -55,7 +55,7 @@ public class ResponseUtil { /** * Utility class */ - private ResponseUtil() { + private TaskResponseUtil() { } public static Reader getResponseContentAsReader(@NotNull HttpResponse response) throws IOException { @@ -134,7 +134,7 @@ public class ResponseUtil { if (LOG.isDebugEnabled()) { String content = getResponseContentAsString(response); TaskUtil.prettyFormatJsonToLog(LOG, content); - return myGson.fromJson(content, myClass); + return myGson.fromJson(content, myClass); } else { return myGson.fromJson(getResponseContentAsReader(response), myClass); @@ -144,10 +144,6 @@ public class ResponseUtil { LOG.warn("Malformed server response", e); return null; } - catch (NumberFormatException e) { - LOG.error("NFE in response: " + getResponseContentAsString(response), e); - throw new RequestFailedException("Malformed response"); - } } } diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/redmine/RedmineRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/redmine/RedmineRepository.java index f497e662cb95..1e134badc6c1 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/redmine/RedmineRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/redmine/RedmineRepository.java @@ -5,7 +5,7 @@ import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.text.StringUtil; import com.intellij.tasks.Task; import com.intellij.tasks.impl.RequestFailedException; -import com.intellij.tasks.impl.gson.GsonUtil; +import com.intellij.tasks.impl.gson.TaskGsonUtil; import com.intellij.tasks.impl.httpclient.NewBaseRepositoryImpl; import com.intellij.tasks.redmine.model.RedmineIssue; import com.intellij.tasks.redmine.model.RedmineProject; @@ -30,7 +30,7 @@ import java.util.Collections; import java.util.List; import java.util.regex.Pattern; -import static com.intellij.tasks.impl.httpclient.ResponseUtil.GsonSingleObjectDeserializer; +import static com.intellij.tasks.impl.httpclient.TaskResponseUtil.GsonSingleObjectDeserializer; import static com.intellij.tasks.redmine.model.RedmineResponseWrapper.*; /** @@ -39,7 +39,7 @@ import static com.intellij.tasks.redmine.model.RedmineResponseWrapper.*; */ @Tag("Redmine") public class RedmineRepository extends NewBaseRepositoryImpl { - private static final Gson GSON = GsonUtil.createDefaultBuilder().create(); + private static final Gson GSON = TaskGsonUtil.createDefaultBuilder().create(); private static final Pattern ID_PATTERN = Pattern.compile("\\d+"); diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java index e2cc5b078150..38d859fee8c9 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloRepository.java @@ -28,9 +28,9 @@ import com.intellij.tasks.TaskBundle; import com.intellij.tasks.TaskRepositoryType; import com.intellij.tasks.impl.BaseRepository; import com.intellij.tasks.impl.httpclient.NewBaseRepositoryImpl; -import com.intellij.tasks.impl.httpclient.ResponseUtil; -import com.intellij.tasks.impl.httpclient.ResponseUtil.GsonMultipleObjectsDeserializer; -import com.intellij.tasks.impl.httpclient.ResponseUtil.GsonSingleObjectDeserializer; +import com.intellij.tasks.impl.httpclient.TaskResponseUtil; +import com.intellij.tasks.impl.httpclient.TaskResponseUtil.GsonMultipleObjectsDeserializer; +import com.intellij.tasks.impl.httpclient.TaskResponseUtil.GsonSingleObjectDeserializer; import com.intellij.tasks.trello.model.TrelloBoard; import com.intellij.tasks.trello.model.TrelloCard; import com.intellij.tasks.trello.model.TrelloList; @@ -346,7 +346,7 @@ public final class TrelloRepository extends NewBaseRepositoryImpl { if (statusLine.getStatusCode() != HttpStatus.SC_OK) { final Header header = response.getFirstHeader("Content-Type"); if (header != null && header.getValue().startsWith("text/plain")) { - final String entityContent = ResponseUtil.getResponseContentAsString(response); + final String entityContent = TaskResponseUtil.getResponseContentAsString(response); throw new Exception(TaskBundle.message("failure.server.message", StringUtil.capitalize(entityContent))); } throw new Exception(TaskBundle.message("failure.http.error", statusLine.getStatusCode(), statusLine.getStatusCode())); diff --git a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloUtil.java b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloUtil.java index 116b08a8ffb7..2533ceefa910 100644 --- a/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloUtil.java +++ b/plugins/tasks/tasks-core/src/com/intellij/tasks/trello/TrelloUtil.java @@ -18,18 +18,15 @@ package com.intellij.tasks.trello; import com.google.gson.*; import com.google.gson.reflect.TypeToken; +import com.intellij.tasks.impl.gson.TaskGsonUtil; import com.intellij.tasks.trello.model.TrelloBoard; import com.intellij.tasks.trello.model.TrelloCard; import com.intellij.tasks.trello.model.TrelloCommentAction; import com.intellij.tasks.trello.model.TrelloList; import java.lang.reflect.Type; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; import java.util.List; -import java.util.TimeZone; +import java.util.Locale; import java.util.regex.Pattern; import static com.intellij.tasks.trello.model.TrelloLabel.LabelColor; @@ -47,33 +44,15 @@ public class TrelloUtil { public static final TypeToken> LIST_OF_COMMENTS_TYPE = new TypeToken>() { /* empty */ }; private static Gson buildGson() { - GsonBuilder gson = new GsonBuilder(); - gson.registerTypeAdapter(Date.class, new DateDeserializer()); + final GsonBuilder gson = TaskGsonUtil.createDefaultBuilder(); gson.registerTypeAdapter(LabelColor.class, new LabelColorDeserializer()); return gson.create(); } - private static class DateDeserializer implements JsonDeserializer { - // Trello send UTC dates, so time zone is always Z - private static final DateFormat ISO8601_DATETIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSS'Z'"); - static { - ISO8601_DATETIME_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC")); - } - @Override - public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - String dateString = json.getAsString(); - try { - return ISO8601_DATETIME_FORMAT.parse(dateString); - } catch (ParseException e) { - throw null; - } - } - } - private static class LabelColorDeserializer implements JsonDeserializer { @Override public LabelColor deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - final String colorName = json.getAsString().toUpperCase(); + final String colorName = json.getAsString().toUpperCase(Locale.US); if (colorName.isEmpty()) { return LabelColor.NO_COLOR; } diff --git a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/GitlabIntegrationTest.java b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/GitlabIntegrationTest.java index e3c7c1574880..b28c190826e3 100644 --- a/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/GitlabIntegrationTest.java +++ b/plugins/tasks/tasks-tests/test/com/intellij/tasks/integration/GitlabIntegrationTest.java @@ -8,7 +8,7 @@ import com.intellij.tasks.gitlab.model.GitlabIssue; import com.intellij.tasks.gitlab.model.GitlabProject; import com.intellij.tasks.impl.LocalTaskImpl; import com.intellij.tasks.impl.TaskUtil; -import com.intellij.tasks.impl.gson.GsonUtil; +import com.intellij.tasks.impl.gson.TaskGsonUtil; import java.util.Collections; @@ -17,7 +17,7 @@ import java.util.Collections; * @author Mikhail Golubev */ public class GitlabIntegrationTest extends TaskManagerTestCase { - private static final Gson GSON = GsonUtil.createDefaultBuilder().create(); + private static final Gson GSON = TaskGsonUtil.createDefaultBuilder().create(); private GitlabRepository myRepository; public void testCommitMessageFormat() throws Exception { diff --git a/python/edu/course-creator-intellij-py/src/PyCCEduProjectTemplate.java b/python/edu/course-creator-intellij-py/src/PyCCEduProjectTemplate.java index d725173154b2..70e622108fab 100644 --- a/python/edu/course-creator-intellij-py/src/PyCCEduProjectTemplate.java +++ b/python/edu/course-creator-intellij-py/src/PyCCEduProjectTemplate.java @@ -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()); } }); } diff --git a/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java b/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java index e4ea96ad67de..4ab1edea86b6 100644 --- a/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java +++ b/python/edu/course-creator-python/src/com/jetbrains/edu/coursecreator/PyCCProjectGenerator.java @@ -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); } diff --git a/python/edu/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java b/python/edu/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java index d49e373e5342..37eb89c49bef 100644 --- a/python/edu/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java +++ b/python/edu/interactive-learning-python/src/com/jetbrains/edu/learning/PyStudyDirectoryProjectGenerator.java @@ -102,7 +102,7 @@ public class PyStudyDirectoryProjectGenerator extends PythonProjectGenerator imp } public List getCourses() { - return myGenerator.getCourses(); + return myGenerator.getCourses(false); } public void setSelectedCourse(CourseInfo course) { diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCChangeCourseInfo.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCChangeCourseInfo.java index 1625f6361c16..e2588978df95 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCChangeCourseInfo.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCChangeCourseInfo.java @@ -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(); diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCPushLesson.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCPushLesson.java index c48d802150c8..f484cff794c2 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCPushLesson.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/actions/CCPushLesson.java @@ -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; } diff --git a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCNewProjectPanel.java b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCNewProjectPanel.java index b5800fcf96d0..5e7de6356b55 100644 --- a/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCNewProjectPanel.java +++ b/python/educational/course-creator/src/com/jetbrains/edu/coursecreator/ui/CCNewProjectPanel.java @@ -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) { diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/courseGeneration/StudyProjectGenerator.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/courseGeneration/StudyProjectGenerator.java index 498948c3e126..63e90f5967a5 100644 --- a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/courseGeneration/StudyProjectGenerator.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/courseGeneration/StudyProjectGenerator.java @@ -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 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 getCourses() { - if (!myCourses.isEmpty()) { + public List getCourses(boolean force) { + if (force || myCourses.isEmpty()) { + myCourses = EduStepicConnector.getCourses(); return myCourses; } else { - myCourses = EduStepicConnector.getCourses(); return myCourses; } } diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyNewProjectPanel.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyNewProjectPanel.java index 679931cd2f2a..afa2484d96a6 100644 --- a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyNewProjectPanel.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyNewProjectPanel.java @@ -3,6 +3,7 @@ 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.jetbrains.edu.courseFormat.Course; import com.jetbrains.edu.learning.StudyUtils; import com.jetbrains.edu.learning.courseGeneration.StudyProjectGenerator; import com.jetbrains.edu.stepic.CourseInfo; @@ -34,7 +35,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 +43,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)); @@ -92,7 +93,7 @@ public class StudyNewProjectPanel{ private class RefreshActionListener implements ActionListener { @Override public void actionPerformed(ActionEvent e) { - final List courses = myGenerator.getCourses(); + final List courses = myGenerator.getCourses(true); if (courses.isEmpty()) { setError(CONNECTION_ERROR); return; @@ -126,7 +127,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); diff --git a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyToolWindowFactory.java b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyToolWindowFactory.java index 739954cee6d5..0539c68a9965 100644 --- a/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyToolWindowFactory.java +++ b/python/educational/interactive-learning/src/com/jetbrains/edu/learning/ui/StudyToolWindowFactory.java @@ -36,8 +36,7 @@ public class StudyToolWindowFactory implements ToolWindowFactory, DumbAware { } String courseName = UIUtil.toHtml("

        " + course.getName() + "

        ", 10); String description = UIUtil.toHtml(course.getDescription(), 5); - String author = taskManager.getCourse().getAuthor(); - String authorLabel = UIUtil.toHtml("Author: " + author, 5); + String authorLabel = UIUtil.toHtml("Author: " + Course.getAuthorsString(course.getAuthors()), 5); contentPanel.add(new JLabel(courseName)); contentPanel.add(new JLabel(authorLabel)); contentPanel.add(Box.createRigidArea(new Dimension(0, 10))); diff --git a/python/educational/src/com/jetbrains/edu/courseFormat/Course.java b/python/educational/src/com/jetbrains/edu/courseFormat/Course.java index 0bde12d2c6ad..36498e4a528b 100644 --- a/python/educational/src/com/jetbrains/edu/courseFormat/Course.java +++ b/python/educational/src/com/jetbrains/edu/courseFormat/Course.java @@ -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 authors = new ArrayList(); 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 getAuthors() { + return authors; } - public void setAuthor(String author) { - this.author = author; + public static String getAuthorsString(@NotNull List authors) { + return StringUtil.join(authors, new Function() { + @Override + public String fun(CourseInfo.Instructor instructor) { + return instructor.getName(); + } + }, ", "); + } + + public void setAuthors(String[] authors) { + this.authors = new ArrayList(); + 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 instructors) { + this.authors = instructors; + } } diff --git a/python/educational/src/com/jetbrains/edu/stepic/CourseInfo.java b/python/educational/src/com/jetbrains/edu/stepic/CourseInfo.java index 38815badc45b..19f8898a3509 100644 --- a/python/educational/src/com/jetbrains/edu/stepic/CourseInfo.java +++ b/python/educational/src/com/jetbrains/edu/stepic/CourseInfo.java @@ -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 " private String myType; - private String myAuthor; - public static CourseInfo INVALID_COURSE = new CourseInfo("", "", "", ""); + @SerializedName("instructors") + List myInstructors = new ArrayList(); - 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 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; + } + } } diff --git a/python/educational/src/com/jetbrains/edu/stepic/EduStepicConnector.java b/python/educational/src/com/jetbrains/edu/stepic/EduStepicConnector.java index 564226d9a06c..f4314caca004 100644 --- a/python/educational/src/com/jetbrains/edu/stepic/EduStepicConnector.java +++ b/python/educational/src/com/jetbrains/edu/stepic/EduStepicConnector.java @@ -8,6 +8,7 @@ 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; @@ -42,7 +43,7 @@ public class EduStepicConnector { private static String ourSessionId = "524iethiwju2tjywaqmf7tbwx0p0jk1b"; private static String ourCSRFToken = "LJ9n6OyLVA7hxU94dlYWUu65MF51Nx37"; //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 EduStepicConnector() { } @@ -61,36 +62,40 @@ public class EduStepicConnector { @NotNull public static List getCourses() { try { - return getFromStepic("courses/99", CoursesContainer.class).courses; + List result = new ArrayList(); + final List courseInfos = + HttpRequests.request(stepicApiUrl + "courses").connect(new HttpRequests.RequestProcessor>() { + + @Override + public List 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; + } + }); + for (CourseInfo info : courseInfos) { + final String courseType = info.getType(); + if (StringUtil.isEmptyOrSpaces(courseType)) continue; + final List 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>() { - - @Override - public List 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 +133,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); diff --git a/python/gen/com/jetbrains/python/lexer/_PythonLexer.java b/python/gen/com/jetbrains/python/lexer/_PythonLexer.java index 214557a92cdb..406490cc2d38 100644 --- a/python/gen/com/jetbrains/python/lexer/_PythonLexer.java +++ b/python/gen/com/jetbrains/python/lexer/_PythonLexer.java @@ -1,4 +1,4 @@ -/* The following code was generated by JFlex 1.4.3 on 4/26/14 11:33 AM */ +/* The following code was generated by JFlex 1.4.3 on 3/24/15 5:33 PM */ /* It's an automatically generated code. Do not modify it. */ package com.jetbrains.python.lexer; @@ -12,8 +12,8 @@ import com.intellij.openapi.util.text.StringUtil; /** * This class is a scanner generated by * JFlex 1.4.3 - * on 4/26/14 11:33 AM from the specification file - * /Users/ignatov/src/ultimate/tools/lexer/../../community/python/src/com/jetbrains/python/lexer/Python.flex + * on 3/24/15 5:33 PM from the specification file + * /home/user/src/idea/tools/lexer/../../community/python/src/com/jetbrains/python/lexer/Python.flex */ class _PythonLexer implements FlexLexer { /** initial size of the lookahead buffer */ @@ -38,15 +38,15 @@ class _PythonLexer implements FlexLexer { * Translates characters to character classes */ private static final String ZZ_CMAP_PACKED = - "\11\0\1\40\1\42\1\0\1\41\1\13\22\0\1\37\1\74\1\36"+ - "\1\12\1\0\1\66\1\67\1\34\1\76\1\77\1\64\1\62\1\105"+ - "\1\26\1\23\1\65\1\1\1\5\6\3\2\2\1\106\1\43\1\73"+ - "\1\63\1\72\1\0\1\104\1\15\1\20\1\31\1\15\1\25\1\15"+ + "\11\0\1\40\1\42\1\0\1\41\1\13\22\0\1\37\1\75\1\36"+ + "\1\12\1\0\1\67\1\70\1\34\1\77\1\100\1\64\1\62\1\105"+ + "\1\26\1\23\1\66\1\1\1\5\6\3\2\2\1\106\1\43\1\74"+ + "\1\63\1\73\1\0\1\65\1\15\1\20\1\31\1\15\1\25\1\15"+ "\3\14\1\27\1\14\1\21\2\14\1\17\2\14\1\32\2\14\1\32"+ - "\2\14\1\16\2\14\1\100\1\35\1\101\1\71\1\14\1\107\1\44"+ + "\2\14\1\16\2\14\1\101\1\35\1\102\1\72\1\14\1\107\1\44"+ "\1\10\1\30\1\46\1\24\1\4\1\57\1\61\1\53\1\27\1\52"+ "\1\11\1\56\1\45\1\7\1\54\1\14\1\50\1\47\1\51\1\33"+ - "\1\14\1\60\1\6\1\55\1\14\1\102\1\70\1\103\1\75\53\0"+ + "\1\14\1\60\1\6\1\55\1\14\1\103\1\71\1\104\1\76\53\0"+ "\1\14\12\0\1\14\4\0\1\14\5\0\27\14\1\0\7\14\30\14"+ "\1\0\10\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ @@ -75,90 +75,108 @@ class _PythonLexer implements FlexLexer { "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ - "\1\14\1\14\1\14\4\14\31\0\140\14\22\14\4\0\14\14\16\0"+ - "\5\14\11\0\1\14\21\0\130\22\5\0\23\22\12\0\1\14\13\0"+ - "\1\14\1\0\3\14\1\0\1\14\1\0\2\14\1\14\21\14\1\0"+ - "\11\14\43\14\1\0\2\14\3\14\3\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\7\14\2\14\1\14\2\14\2\14\1\14\1\14"+ + "\4\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\105\14"+ + "\1\14\33\14\22\14\4\0\14\14\16\0\5\14\7\0\1\14\1\0"+ + "\1\14\21\0\160\22\1\14\1\14\1\14\1\14\1\14\1\0\1\14"+ + "\1\14\2\0\1\14\3\14\10\0\1\14\1\0\3\14\1\0\1\14"+ + "\1\0\2\14\1\14\21\14\1\0\11\14\43\14\1\14\2\14\3\14"+ + "\3\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ - "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\5\14"+ - "\1\14\1\14\1\0\1\14\1\14\2\14\1\14\4\0\60\14\60\14"+ + "\1\14\1\14\1\14\1\14\5\14\1\14\1\14\1\0\1\14\1\14"+ + "\2\14\2\14\63\14\60\14\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\0\5\22"+ + "\2\0\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ - "\1\14\1\14\1\14\1\14\1\0\4\22\3\0\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\2\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\2\14\1\14"+ "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ - "\1\14\2\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ - "\1\14\1\14\1\14\1\14\1\14\1\0\1\14\1\14\1\14\1\14"+ "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ - "\1\14\1\14\1\14\1\14\2\0\1\14\1\14\6\0\1\14\1\14"+ - "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ - "\1\14\1\14\1\14\1\14\41\0\46\14\2\0\1\14\7\0\47\14"+ - "\11\0\21\22\1\0\27\22\1\0\3\22\1\0\1\22\1\0\2\22"+ - "\1\0\1\22\13\0\33\14\5\0\3\14\35\0\6\22\13\0\32\14"+ - "\5\0\1\14\12\14\16\22\7\0\12\22\4\0\2\14\1\22\143\14"+ - "\1\0\1\14\7\22\2\0\6\22\2\14\2\22\1\0\4\22\2\14"+ - "\12\22\3\14\2\0\1\14\20\0\1\14\1\22\36\14\33\22\2\0"+ - "\3\14\60\0\46\14\13\22\1\14\u014f\0\2\22\1\22\66\14\2\0"+ - "\1\22\1\14\3\22\10\22\4\22\1\22\2\0\1\14\4\22\3\0"+ - "\12\14\2\22\2\0\12\22\21\0\1\22\2\22\1\0\10\14\2\0"+ - "\2\14\2\0\26\14\1\0\7\14\1\0\1\14\3\0\4\14\2\0"+ - "\1\22\1\14\3\22\4\22\2\0\2\22\2\0\2\22\1\22\11\0"+ - "\1\22\4\0\2\14\1\0\3\14\2\22\2\0\12\22\2\14\17\0"+ - "\2\22\1\22\1\0\6\14\4\0\2\14\2\0\26\14\1\0\7\14"+ - "\1\0\2\14\1\0\2\14\1\0\2\14\2\0\1\22\1\0\3\22"+ - "\2\22\4\0\2\22\2\0\3\22\13\0\4\14\1\0\1\14\7\0"+ - "\12\22\2\22\3\14\14\0\2\22\1\22\1\0\11\14\1\0\3\14"+ - "\1\0\26\14\1\0\7\14\1\0\2\14\1\0\5\14\2\0\1\22"+ - "\1\14\3\22\5\22\1\0\2\22\1\22\1\0\2\22\1\22\2\0"+ - "\1\14\17\0\2\14\2\22\2\0\12\22\21\0\1\22\2\22\1\0"+ - "\10\14\2\0\2\14\2\0\26\14\1\0\7\14\1\0\2\14\1\0"+ - "\5\14\2\0\1\22\1\14\1\22\1\22\1\22\3\22\3\0\2\22"+ - "\2\0\2\22\1\22\10\0\1\22\1\22\4\0\2\14\1\0\3\14"+ - "\4\0\12\22\1\0\1\14\20\0\1\22\1\14\1\0\6\14\3\0"+ - "\3\14\1\0\4\14\3\0\2\14\1\0\1\14\1\0\2\14\3\0"+ - "\2\14\3\0\3\14\3\0\10\14\1\0\3\14\4\0\2\22\1\22"+ - "\2\22\3\0\3\22\1\0\3\22\1\22\11\0\1\22\17\0\11\22"+ - "\21\0\3\22\1\0\10\14\1\0\3\14\1\0\27\14\1\0\12\14"+ - "\1\0\5\14\4\0\3\22\4\22\1\0\3\22\1\0\4\22\7\0"+ - "\2\22\11\0\2\14\4\0\12\22\22\0\2\22\1\0\10\14\1\0"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\11\0\46\14\2\0"+ + "\1\14\7\0\47\14\11\0\55\22\1\0\1\22\1\0\2\22\1\0"+ + "\2\22\1\0\1\22\10\0\33\14\5\0\3\14\35\0\13\22\5\0"+ + "\40\14\1\14\12\14\25\22\12\22\4\0\2\14\1\22\143\14\1\0"+ + "\1\14\7\22\2\0\6\22\2\14\2\22\1\0\4\22\2\14\12\22"+ + "\3\14\2\0\1\14\20\0\1\14\1\22\36\14\33\22\2\0\131\14"+ + "\13\22\1\14\16\0\12\22\41\14\11\22\2\14\4\0\1\14\5\0"+ + "\26\14\4\22\1\14\11\22\1\14\3\22\1\14\5\22\22\0\31\14"+ + "\3\22\244\0\3\22\1\22\66\14\1\22\1\22\1\22\1\14\3\22"+ + "\10\22\4\22\1\22\2\22\1\14\7\22\12\14\2\22\2\0\12\22"+ + "\1\0\1\14\6\14\1\0\7\14\1\0\1\22\2\22\1\0\10\14"+ + "\2\0\2\14\2\0\26\14\1\0\7\14\1\0\1\14\3\0\4\14"+ + "\2\0\1\22\1\14\3\22\4\22\2\0\2\22\2\0\2\22\1\22"+ + "\1\14\10\0\1\22\4\0\2\14\1\0\3\14\2\22\2\0\12\22"+ + "\2\14\17\0\2\22\1\22\1\0\6\14\4\0\2\14\2\0\26\14"+ + "\1\0\7\14\1\0\2\14\1\0\2\14\1\0\2\14\2\0\1\22"+ + "\1\0\3\22\2\22\4\0\2\22\2\0\3\22\3\0\1\22\7\0"+ + "\4\14\1\0\1\14\7\0\12\22\2\22\3\14\1\22\13\0\2\22"+ + "\1\22\1\0\11\14\1\0\3\14\1\0\26\14\1\0\7\14\1\0"+ + "\2\14\1\0\5\14\2\0\1\22\1\14\3\22\5\22\1\0\2\22"+ + "\1\22\1\0\2\22\1\22\2\0\1\14\17\0\2\14\2\22\2\0"+ + "\12\22\21\0\1\22\2\22\1\0\10\14\2\0\2\14\2\0\26\14"+ + "\1\0\7\14\1\0\2\14\1\0\5\14\2\0\1\22\1\14\1\22"+ + "\1\22\1\22\4\22\2\0\2\22\2\0\2\22\1\22\10\0\1\22"+ + "\1\22\4\0\2\14\1\0\3\14\2\22\2\0\12\22\1\0\1\14"+ + "\20\0\1\22\1\14\1\0\6\14\3\0\3\14\1\0\4\14\3\0"+ + "\2\14\1\0\1\14\1\0\2\14\3\0\2\14\3\0\3\14\3\0"+ + "\14\14\4\0\2\22\1\22\2\22\3\0\3\22\1\0\3\22\1\22"+ + "\2\0\1\14\6\0\1\22\16\0\12\22\21\0\3\22\1\0\10\14"+ + "\1\0\3\14\1\0\27\14\1\0\12\14\1\0\5\14\3\0\1\14"+ + "\3\22\4\22\1\0\3\22\1\0\4\22\7\0\2\22\1\0\2\14"+ + "\6\0\2\14\2\22\2\0\12\22\22\0\2\22\1\0\10\14\1\0"+ "\3\14\1\0\27\14\1\0\12\14\1\0\5\14\2\0\1\22\1\14"+ "\1\22\1\22\5\22\1\0\1\22\2\22\1\0\2\22\2\22\7\0"+ - "\2\22\7\0\1\14\1\0\2\14\4\0\12\22\22\0\2\22\1\0"+ - "\10\14\1\0\3\14\1\0\27\14\1\0\20\14\4\0\3\22\3\22"+ - "\2\0\3\22\1\0\3\22\1\22\11\0\1\22\10\0\2\14\4\0"+ - "\12\22\22\0\2\22\1\0\22\14\3\0\30\14\1\0\11\14\1\0"+ - "\1\14\2\0\7\14\3\0\1\22\4\0\3\22\3\22\1\0\1\22"+ - "\1\0\10\22\22\0\2\22\15\0\60\14\1\22\2\14\7\22\5\0"+ - "\6\14\1\14\10\22\1\0\12\22\47\0\2\14\1\0\1\14\2\0"+ - "\2\14\1\0\1\14\2\0\1\14\6\0\4\14\1\0\7\14\1\0"+ - "\3\14\1\0\1\14\1\0\1\14\2\0\2\14\1\0\4\14\1\22"+ - "\2\14\6\22\1\0\2\22\1\14\2\0\5\14\1\0\1\14\1\0"+ - "\6\22\2\0\12\22\2\0\2\14\42\0\1\14\27\0\2\22\6\0"+ - "\12\22\13\0\1\22\1\0\1\22\1\0\1\22\4\0\2\22\10\14"+ - "\1\0\42\14\6\0\16\22\1\22\5\22\1\0\2\22\4\14\4\0"+ - "\10\22\1\0\44\22\11\0\1\22\71\0\42\14\1\0\5\14\1\0"+ - "\2\14\1\0\1\22\4\22\1\22\1\22\3\0\2\22\1\22\1\22"+ - "\6\0\12\22\6\0\6\14\2\22\2\22\106\0\46\14\12\0\51\14"+ - "\7\0\132\14\5\0\104\14\5\0\122\14\6\0\7\14\1\0\77\14"+ - "\1\0\1\14\1\0\4\14\2\0\7\14\1\0\1\14\1\0\4\14"+ - "\2\0\47\14\1\0\1\14\1\0\4\14\2\0\37\14\1\0\1\14"+ - "\1\0\4\14\2\0\7\14\1\0\1\14\1\0\4\14\2\0\7\14"+ - "\1\0\7\14\1\0\27\14\1\0\37\14\1\0\1\14\1\0\4\14"+ - "\2\0\7\14\1\0\47\14\1\0\23\14\16\0\11\22\56\0\125\14"+ - "\14\0\u026c\14\2\0\10\14\12\0\32\14\5\0\113\14\3\0\3\14"+ - "\17\0\15\14\1\0\4\14\3\22\13\0\22\14\3\22\13\0\22\14"+ - "\2\22\14\0\15\14\1\0\3\14\1\0\2\22\14\0\64\14\2\0"+ - "\1\22\7\22\10\22\1\22\2\22\13\22\3\0\1\14\4\0\1\14"+ - "\1\22\2\0\12\22\41\0\3\22\2\0\12\22\6\0\43\14\1\14"+ - "\64\14\10\0\51\14\1\22\126\0\35\14\3\0\3\22\4\22\2\22"+ - "\3\22\4\0\2\22\1\22\6\22\3\22\12\0\12\22\36\14\2\0"+ - "\5\14\u038b\0\54\14\66\14\12\14\224\0\1\14\1\14\1\14\1\14"+ + "\2\22\7\0\1\14\1\0\2\14\2\22\2\0\12\22\1\0\2\14"+ + "\17\0\2\22\1\0\10\14\1\0\3\14\1\0\51\14\2\0\1\14"+ + "\3\22\4\22\1\0\3\22\1\0\3\22\1\22\1\14\10\0\1\22"+ + "\10\0\2\14\2\22\2\0\12\22\12\0\6\14\2\0\2\22\1\0"+ + "\22\14\3\0\30\14\1\0\11\14\1\0\1\14\2\0\7\14\3\0"+ + "\1\22\4\0\3\22\3\22\1\0\1\22\1\0\10\22\22\0\2\22"+ + "\15\0\60\14\1\22\2\14\7\22\5\0\6\14\1\14\10\22\1\0"+ + "\12\22\47\0\2\14\1\0\1\14\2\0\2\14\1\0\1\14\2\0"+ + "\1\14\6\0\4\14\1\0\7\14\1\0\3\14\1\0\1\14\1\0"+ + "\1\14\2\0\2\14\1\0\4\14\1\22\2\14\6\22\1\0\2\22"+ + "\1\14\2\0\5\14\1\0\1\14\1\0\6\22\2\0\12\22\2\0"+ + "\2\14\42\0\1\14\27\0\2\22\6\0\12\22\13\0\1\22\1\0"+ + "\1\22\1\0\1\22\4\0\2\22\10\14\1\0\44\14\4\0\16\22"+ + "\1\22\5\22\1\0\2\22\5\14\13\22\1\0\44\22\11\0\1\22"+ + "\71\0\53\14\2\22\4\22\1\22\6\22\1\22\2\22\2\22\2\22"+ + "\1\14\12\22\6\0\6\14\2\22\2\22\4\14\3\22\1\14\3\22"+ + "\2\14\7\22\3\14\4\22\15\14\1\22\2\22\2\22\6\22\1\22"+ + "\1\14\1\22\12\22\3\22\1\22\2\0\46\14\12\0\53\14\1\0"+ + "\1\14\3\0\u0149\14\1\0\4\14\2\0\7\14\1\0\1\14\1\0"+ + "\4\14\2\0\51\14\1\0\4\14\2\0\41\14\1\0\4\14\2\0"+ + "\7\14\1\0\1\14\1\0\4\14\2\0\17\14\1\0\71\14\1\0"+ + "\4\14\2\0\103\14\2\0\3\22\40\0\20\14\20\0\125\14\14\0"+ + "\u026c\14\2\0\21\14\1\0\32\14\5\0\113\14\3\0\3\14\17\0"+ + "\15\14\1\0\4\14\3\22\13\0\22\14\3\22\13\0\22\14\2\22"+ + "\14\0\15\14\1\0\3\14\1\0\2\22\14\0\64\14\2\0\1\22"+ + "\7\22\10\22\1\22\2\22\13\22\3\0\1\14\4\0\1\14\1\22"+ + "\2\0\12\22\41\0\3\22\2\0\12\22\6\0\43\14\1\14\64\14"+ + "\10\0\51\14\1\22\1\14\5\0\106\14\12\0\35\14\3\0\3\22"+ + "\4\22\2\22\3\22\4\0\2\22\1\22\6\22\3\22\12\0\12\22"+ + "\36\14\2\0\5\14\13\0\54\14\4\0\21\22\7\14\2\22\6\0"+ + "\12\22\46\0\27\14\2\22\3\22\4\0\65\14\1\22\1\22\1\22"+ + "\7\22\1\0\1\22\1\22\1\22\2\22\10\22\6\22\12\22\2\0"+ + "\1\22\12\22\6\0\12\22\15\0\1\14\130\0\4\22\1\22\57\14"+ + "\1\22\1\22\5\22\1\22\1\22\5\22\1\22\2\22\7\14\4\0"+ + "\12\22\21\0\11\22\14\0\2\22\1\22\36\14\1\22\4\22\2\22"+ + "\2\22\1\22\3\0\2\14\12\22\6\0\46\14\1\22\1\22\2\22"+ + "\3\22\1\22\1\22\3\22\2\22\14\0\44\14\10\22\10\22\2\22"+ + "\2\22\10\0\12\22\3\0\3\14\12\22\36\14\6\14\122\0\3\22"+ + "\1\0\15\22\1\22\7\22\4\14\1\22\4\14\1\22\15\0\54\14"+ + "\66\14\26\14\1\14\42\14\45\14\47\22\25\0\4\22\1\14\1\14"+ "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ @@ -173,7 +191,7 @@ class _PythonLexer implements FlexLexer { "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ - "\1\14\1\14\1\14\1\14\1\14\7\14\4\0\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\11\14\1\14\1\14"+ "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ @@ -182,28 +200,77 @@ class _PythonLexer implements FlexLexer { "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ - "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\6\0\10\14\10\14"+ - "\6\14\2\0\6\14\2\0\10\14\10\14\10\14\10\14\6\14\2\0"+ - "\6\14\2\0\10\14\1\0\1\14\1\0\1\14\1\0\1\14\1\0"+ - "\1\14\10\14\10\14\16\14\2\0\10\14\10\14\10\14\10\14\10\14"+ - "\10\14\5\14\1\0\2\14\4\14\1\14\1\0\1\14\3\0\3\14"+ - "\1\0\2\14\4\14\1\14\3\0\4\14\2\0\2\14\4\14\4\0"+ - "\10\14\5\14\5\0\3\14\1\0\2\14\4\14\1\14\102\0\2\22"+ - "\23\0\1\22\34\0\1\14\15\0\1\14\120\0\15\22\4\0\1\22"+ - "\3\0\6\22\27\0\1\14\4\0\1\14\2\0\1\14\3\14\2\14"+ - "\3\14\1\14\1\0\1\14\3\0\5\14\6\0\1\14\1\0\1\14"+ - "\1\0\1\14\1\0\4\14\1\0\1\14\2\14\1\0\1\14\1\14"+ - "\4\14\1\14\3\0\1\14\2\14\5\0\1\14\4\14\26\0\44\14"+ - "\u0e81\0\1\14\1\14\1\14\31\0\11\14\6\22\1\0\5\14\2\0"+ - "\3\14\1\14\1\14\4\0\126\14\2\0\2\22\2\0\2\14\1\14"+ - "\1\0\132\14\1\22\3\14\1\14\5\0\50\14\4\0\136\14\21\0"+ - "\30\14\70\0\20\14\u0200\0\u19b6\14\112\0\u51a6\14\132\0\u048d\14\u0773\0"+ - "\u2ba4\14\u215c\0\u012e\14\2\0\73\14\225\0\7\14\14\0\5\14\5\0"+ - "\1\14\1\22\12\14\1\0\15\14\1\0\5\14\1\0\1\14\1\0"+ - "\2\14\1\0\2\14\1\0\154\14\41\0\u016b\14\22\0\100\14\2\0"+ - "\66\14\50\0\14\14\4\0\20\22\20\0\4\22\17\0\2\22\30\0"+ - "\3\22\40\0\5\14\1\0\207\14\23\0\12\22\7\0\32\14\4\0"+ - "\1\22\1\0\32\14\12\0\1\22\12\14\1\14\55\14\2\14\37\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\11\14\10\14\6\14\2\0\6\14"+ + "\2\0\10\14\10\14\10\14\10\14\6\14\2\0\6\14\2\0\10\14"+ + "\1\0\1\14\1\0\1\14\1\0\1\14\1\0\1\14\10\14\10\14"+ + "\16\14\2\0\10\14\10\14\10\14\10\14\10\14\10\14\5\14\1\0"+ + "\2\14\4\14\1\14\1\0\1\14\3\0\3\14\1\0\2\14\4\14"+ + "\1\14\3\0\4\14\2\0\2\14\4\14\4\0\10\14\5\14\5\0"+ + "\3\14\1\0\2\14\4\14\1\14\102\0\2\22\23\0\1\22\34\0"+ + "\1\14\15\0\1\14\20\0\15\14\63\0\15\22\4\0\1\22\3\0"+ + "\14\22\21\0\1\14\4\0\1\14\2\0\1\14\3\14\2\14\3\14"+ + "\1\14\1\0\1\14\3\0\5\14\6\0\1\14\1\0\1\14\1\0"+ + "\1\14\1\0\4\14\1\0\1\14\4\14\1\14\4\14\1\14\2\0"+ + "\2\14\2\14\5\0\1\14\4\14\4\0\1\14\21\0\43\14\1\14"+ + "\1\14\4\14\u0a77\0\57\14\1\0\57\14\1\0\1\14\1\14\3\14"+ + "\2\14\1\14\1\14\1\14\1\14\1\14\1\14\4\14\1\14\1\14"+ + "\2\14\1\14\7\14\1\14\3\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\2\14\6\0\1\14\1\14\1\14\1\14\3\22"+ + "\16\0\46\14\12\0\66\14\11\0\1\14\17\0\1\22\27\14\11\0"+ + "\7\14\1\0\7\14\1\0\7\14\1\0\7\14\1\0\7\14\1\0"+ + "\7\14\1\0\7\14\1\0\7\14\1\0\40\22\57\0\1\14\u01d5\0"+ + "\1\14\1\14\1\14\31\0\11\14\6\22\1\0\5\14\2\0\3\14"+ + "\1\14\1\14\4\0\126\14\2\0\2\22\2\0\2\14\1\14\1\0"+ + "\132\14\1\0\3\14\1\14\5\0\51\14\3\0\136\14\21\0\33\14"+ + "\65\0\20\14\u0200\0\u19b6\14\112\0\u51cc\14\64\0\25\14\1\14\u0477\14"+ + "\103\0\50\14\6\14\2\0\u010c\14\1\14\3\0\20\14\12\22\2\14"+ + "\24\0\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\22\14\0"+ + "\2\22\1\0\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\10\0\106\14\12\14"+ + "\2\22\45\0\11\14\2\0\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\3\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14\1\14"+ + "\1\14\10\14\1\14\1\14\1\14\1\14\2\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\1\14\2\0\1\14\1\14"+ + "\1\14\1\14\1\0\1\14\1\14\16\0\1\14\1\14\1\14\1\14"+ + "\1\14\1\14\1\14\1\14\1\14\1\14\120\0\1\14\7\14\1\22"+ + "\3\14\1\22\4\14\1\22\27\14\2\22\2\22\1\22\30\0\64\14"+ + "\14\0\2\22\62\14\20\22\1\22\13\0\12\22\6\0\22\22\6\14"+ + "\3\0\1\14\4\0\12\22\34\14\10\22\2\0\27\14\13\22\2\22"+ + "\14\0\35\14\3\0\3\22\1\22\57\14\1\22\2\22\4\22\2\22"+ + "\1\22\4\22\16\0\1\14\12\22\46\0\51\14\6\22\2\22\2\22"+ + "\2\22\2\22\11\0\3\14\1\22\10\14\1\22\1\22\2\0\12\22"+ + "\6\0\20\14\1\14\6\14\3\0\1\14\1\22\4\0\60\14\1\22"+ + "\1\14\3\22\2\14\2\22\5\14\2\22\1\14\1\22\1\14\30\0"+ + "\2\14\1\14\43\0\6\14\2\0\6\14\2\0\6\14\11\0\7\14"+ + "\1\0\7\14\221\0\43\14\2\22\1\22\2\22\1\22\2\22\1\0"+ + "\1\22\1\22\2\0\12\22\6\0\u2ba4\14\14\0\27\14\4\0\61\14"+ + "\u2104\0\u012e\14\2\0\76\14\2\0\152\14\46\0\7\14\14\0\5\14"+ + "\5\0\1\14\1\22\12\14\1\0\15\14\1\0\5\14\1\0\1\14"+ + "\1\0\2\14\1\0\2\14\1\0\154\14\41\0\u016b\14\22\0\100\14"+ + "\2\0\66\14\50\0\14\14\4\0\20\22\20\0\7\22\14\0\2\22"+ + "\30\0\3\22\40\0\5\14\1\0\207\14\23\0\12\22\7\0\32\14"+ + "\4\0\1\22\1\0\32\14\13\0\12\14\1\14\55\14\2\14\37\14"+ "\3\0\6\14\2\0\6\14\2\0\6\14\2\0\3\14\43\0"; /** @@ -220,29 +287,29 @@ class _PythonLexer implements FlexLexer { "\3\0\1\1\2\2\5\3\1\4\1\3\1\5\1\3"+ "\1\6\1\3\1\7\1\10\1\7\1\11\1\12\1\13"+ "\1\14\1\15\12\3\1\16\1\17\1\20\1\21\1\22"+ - "\1\23\1\24\1\25\1\26\1\27\1\1\1\30\1\31"+ + "\1\23\1\24\1\25\1\26\1\27\1\30\1\1\1\31"+ "\1\32\1\33\1\34\1\35\1\36\1\37\1\40\1\41"+ "\1\42\2\43\1\44\2\45\1\46\3\3\2\47\1\3"+ "\1\41\1\2\4\0\1\2\1\50\1\0\1\51\3\3"+ "\1\52\5\3\1\53\2\3\3\7\1\54\3\7\7\3"+ "\1\55\1\56\1\57\5\3\1\60\1\61\1\62\1\63"+ "\1\64\1\65\1\66\1\67\1\70\1\71\1\72\1\73"+ - "\1\74\1\75\1\76\1\77\1\0\3\45\1\100\3\45"+ - "\2\3\6\47\2\0\1\101\3\2\1\50\1\0\1\102"+ - "\12\3\1\7\1\103\1\104\1\0\1\103\1\105\1\3"+ - "\1\106\1\107\1\110\2\3\1\111\5\3\1\112\1\113"+ - "\1\114\1\115\1\0\1\45\1\116\1\117\1\0\1\116"+ - "\1\3\1\47\2\120\1\121\1\3\2\0\3\3\1\122"+ - "\1\123\2\3\1\0\2\124\1\0\4\3\1\125\3\3"+ - "\3\0\2\117\7\0\1\3\2\0\1\126\3\3\1\127"+ - "\1\0\2\103\1\0\2\3\1\130\1\3\1\131\1\3"+ - "\1\132\3\0\2\116\4\0\2\120\1\0\1\3\1\133"+ - "\1\134\1\3\3\103\1\135\1\136\1\137\1\140\3\116"+ - "\3\120\1\141\1\3\1\124\1\0\1\142\6\0\1\143"+ - "\2\103\2\116\2\120"; + "\1\74\1\75\1\76\1\77\1\100\1\0\3\45\1\101"+ + "\3\45\2\3\6\47\2\0\1\102\3\2\1\50\1\0"+ + "\1\103\12\3\1\7\1\104\1\105\1\0\1\104\1\106"+ + "\1\3\1\107\1\110\1\111\2\3\1\112\5\3\1\113"+ + "\1\114\1\115\1\116\1\0\1\45\1\117\1\120\1\0"+ + "\1\117\1\3\1\47\2\121\1\122\1\3\2\0\3\3"+ + "\1\123\1\124\2\3\1\0\2\125\1\0\4\3\1\126"+ + "\3\3\3\0\2\120\7\0\1\3\2\0\1\127\3\3"+ + "\1\130\1\0\2\104\1\0\2\3\1\131\1\3\1\132"+ + "\1\3\1\133\3\0\2\117\4\0\2\121\1\0\1\3"+ + "\1\134\1\135\1\3\3\104\1\136\1\137\1\140\1\141"+ + "\3\117\3\121\1\142\1\3\1\125\1\0\1\143\6\0"+ + "\1\144\2\104\2\117\2\121"; private static int [] zzUnpackAction() { - int [] result = new int[297]; + int [] result = new int[298]; int offset = 0; offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); return result; @@ -272,42 +339,42 @@ class _PythonLexer implements FlexLexer { "\0\u0480\0\u04c8\0\330\0\u0510\0\330\0\330\0\330\0\330"+ "\0\330\0\u0558\0\u05a0\0\u05e8\0\u0630\0\u0678\0\u06c0\0\u0708"+ "\0\u0750\0\u0798\0\u07e0\0\u0828\0\u0870\0\u08b8\0\u0900\0\u0948"+ - "\0\u0990\0\u09d8\0\u0a20\0\u0a68\0\u0ab0\0\u0af8\0\330\0\330"+ + "\0\u0990\0\u09d8\0\u0a20\0\u0a68\0\u0ab0\0\u0af8\0\u0b40\0\330"+ "\0\330\0\330\0\330\0\330\0\330\0\330\0\330\0\330"+ - "\0\330\0\330\0\u0b40\0\u0b88\0\u0bd0\0\u0c18\0\330\0\u0c60"+ - "\0\u0ca8\0\u0cf0\0\u0d38\0\u0d80\0\u0dc8\0\u0e10\0\u0e58\0\u0ea0"+ - "\0\u0ee8\0\u0f30\0\u0f78\0\330\0\u0fc0\0\u1008\0\330\0\u1050"+ - "\0\u1098\0\u10e0\0\u01f8\0\u1128\0\u1170\0\u11b8\0\u1200\0\u1248"+ - "\0\330\0\u1290\0\u12d8\0\u1320\0\u1368\0\u13b0\0\330\0\u13f8"+ - "\0\u1440\0\u1488\0\u14d0\0\u1518\0\u1560\0\u15a8\0\u15f0\0\u1638"+ - "\0\u1680\0\u01f8\0\u01f8\0\u01f8\0\u16c8\0\u1710\0\u1758\0\u17a0"+ - "\0\u17e8\0\330\0\330\0\330\0\u1830\0\330\0\u1878\0\330"+ - "\0\330\0\330\0\330\0\330\0\u18c0\0\330\0\330\0\u1908"+ - "\0\330\0\u1950\0\u1998\0\u19e0\0\u1a28\0\330\0\u1a70\0\u1ab8"+ + "\0\330\0\330\0\u0b88\0\u0bd0\0\u0c18\0\u0c60\0\330\0\u0ca8"+ + "\0\u0cf0\0\u0d38\0\u0d80\0\u0dc8\0\u0e10\0\u0e58\0\u0ea0\0\u0ee8"+ + "\0\u0f30\0\u0f78\0\u0fc0\0\330\0\u1008\0\u1050\0\330\0\u1098"+ + "\0\u10e0\0\u1128\0\u01f8\0\u1170\0\u11b8\0\u1200\0\u1248\0\u1290"+ + "\0\330\0\u12d8\0\u1320\0\u1368\0\u13b0\0\u13f8\0\330\0\u1440"+ + "\0\u1488\0\u14d0\0\u1518\0\u1560\0\u15a8\0\u15f0\0\u1638\0\u1680"+ + "\0\u16c8\0\u01f8\0\u01f8\0\u01f8\0\u1710\0\u1758\0\u17a0\0\u17e8"+ + "\0\u1830\0\330\0\330\0\330\0\u1878\0\330\0\330\0\u18c0"+ + "\0\330\0\330\0\330\0\330\0\330\0\u1908\0\330\0\330"+ + "\0\u1950\0\330\0\u1998\0\u19e0\0\u1a28\0\u1a70\0\330\0\u1ab8"+ "\0\u1b00\0\u1b48\0\u1b90\0\u1bd8\0\u1c20\0\u1c68\0\u1cb0\0\u1cf8"+ - "\0\u1d40\0\u1d88\0\u0e10\0\330\0\u1dd0\0\u1e18\0\u1e60\0\u1ea8"+ - "\0\u1ef0\0\u01f8\0\u1f38\0\u1f80\0\u1fc8\0\u2010\0\u2058\0\u20a0"+ - "\0\u20e8\0\u2130\0\u2178\0\u21c0\0\u2208\0\u2250\0\330\0\u2208"+ - "\0\u2298\0\u01f8\0\u22e0\0\u01f8\0\u01f8\0\u01f8\0\u2328\0\u2370"+ - "\0\u01f8\0\u23b8\0\u2400\0\u2448\0\u2490\0\u24d8\0\330\0\330"+ - "\0\330\0\330\0\u2520\0\u2568\0\u25b0\0\330\0\u2568\0\u25f8"+ - "\0\u2640\0\330\0\u2688\0\u26d0\0\u01f8\0\u2718\0\u2760\0\u27a8"+ - "\0\u27f0\0\u2838\0\u2880\0\u01f8\0\u01f8\0\u28c8\0\u2910\0\u2958"+ - "\0\u29a0\0\u29e8\0\u2a30\0\u2a78\0\u2ac0\0\u2b08\0\u2b50\0\u01f8"+ - "\0\u2b98\0\u2be0\0\u2c28\0\u2c70\0\u2cb8\0\u2d00\0\u2d48\0\u2d90"+ + "\0\u1d40\0\u1d88\0\u1dd0\0\u0e58\0\330\0\u1e18\0\u1e60\0\u1ea8"+ + "\0\u1ef0\0\u1f38\0\u01f8\0\u1f80\0\u1fc8\0\u2010\0\u2058\0\u20a0"+ + "\0\u20e8\0\u2130\0\u2178\0\u21c0\0\u2208\0\u2250\0\u2298\0\330"+ + "\0\u2250\0\u22e0\0\u01f8\0\u2328\0\u01f8\0\u01f8\0\u01f8\0\u2370"+ + "\0\u23b8\0\u01f8\0\u2400\0\u2448\0\u2490\0\u24d8\0\u2520\0\330"+ + "\0\330\0\330\0\330\0\u2568\0\u25b0\0\u25f8\0\330\0\u25b0"+ + "\0\u2640\0\u2688\0\330\0\u26d0\0\u2718\0\u01f8\0\u2760\0\u27a8"+ + "\0\u27f0\0\u2838\0\u2880\0\u28c8\0\u01f8\0\u01f8\0\u2910\0\u2958"+ + "\0\u29a0\0\u29e8\0\u2a30\0\u2a78\0\u2ac0\0\u2b08\0\u2b50\0\u2b98"+ + "\0\u01f8\0\u2be0\0\u2c28\0\u2c70\0\u2cb8\0\u2d00\0\u2d48\0\u2d90"+ "\0\u2dd8\0\u2e20\0\u2e68\0\u2eb0\0\u2ef8\0\u2f40\0\u2f88\0\u2fd0"+ - "\0\u3018\0\u3060\0\u01f8\0\u30a8\0\u30f0\0\u3138\0\u01f8\0\u3180"+ - "\0\u31c8\0\u3210\0\u3258\0\u32a0\0\u32e8\0\u01f8\0\u3330\0\u01f8"+ - "\0\u3378\0\u01f8\0\u33c0\0\u3408\0\u3450\0\u3498\0\u34e0\0\u3528"+ - "\0\u1c20\0\u1d40\0\u3570\0\u35b8\0\u3600\0\u3648\0\u3690\0\u01f8"+ - "\0\u01f8\0\u36d8\0\u3720\0\u3768\0\u37b0\0\u01f8\0\u01f8\0\u01f8"+ - "\0\u01f8\0\u2568\0\u37f8\0\u3840\0\330\0\u3888\0\u38d0\0\u01f8"+ - "\0\u3918\0\330\0\u3720\0\330\0\u3960\0\u39a8\0\u39f0\0\u3a38"+ - "\0\u3a80\0\u3ac8\0\u01f8\0\u3180\0\u3258\0\u3450\0\u3528\0\u3570"+ - "\0\u3648"; + "\0\u3018\0\u3060\0\u30a8\0\u01f8\0\u30f0\0\u3138\0\u3180\0\u01f8"+ + "\0\u31c8\0\u3210\0\u3258\0\u32a0\0\u32e8\0\u3330\0\u01f8\0\u3378"+ + "\0\u01f8\0\u33c0\0\u01f8\0\u3408\0\u3450\0\u3498\0\u34e0\0\u3528"+ + "\0\u3570\0\u1c68\0\u1d88\0\u35b8\0\u3600\0\u3648\0\u3690\0\u36d8"+ + "\0\u01f8\0\u01f8\0\u3720\0\u3768\0\u37b0\0\u37f8\0\u01f8\0\u01f8"+ + "\0\u01f8\0\u01f8\0\u25b0\0\u3840\0\u3888\0\330\0\u38d0\0\u3918"+ + "\0\u01f8\0\u3960\0\330\0\u3768\0\330\0\u39a8\0\u39f0\0\u3a38"+ + "\0\u3a80\0\u3ac8\0\u3b10\0\u01f8\0\u31c8\0\u32a0\0\u3498\0\u3570"+ + "\0\u35b8\0\u3690"; private static int [] zzUnpackRowMap() { - int [] result = new int[297]; + int [] result = new int[298]; int offset = 0; offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); return result; @@ -389,185 +456,185 @@ class _PythonLexer implements FlexLexer { "\10\10\1\160\2\0\7\10\1\0\2\10\1\0\5\10"+ "\10\0\16\10\27\0\11\10\2\0\7\10\1\0\2\10"+ "\1\0\5\10\10\0\15\10\1\161\111\0\1\162\107\0"+ - "\1\163\107\0\1\164\1\165\106\0\1\166\1\0\1\167"+ - "\105\0\1\170\107\0\1\171\107\0\1\172\107\0\1\173"+ - "\107\0\1\174\6\0\1\175\100\0\1\176\6\0\1\177"+ - "\1\200\77\0\1\201\34\0\1\202\7\0\1\202\7\0"+ - "\4\202\1\75\1\0\1\76\11\0\1\202\37\0\13\74"+ - "\1\0\26\74\1\0\45\74\13\203\1\0\20\203\1\204"+ - "\1\205\4\203\1\206\45\203\13\207\1\0\21\207\1\210"+ - "\1\211\3\207\1\206\45\207\1\0\7\10\1\212\1\10"+ - "\2\0\4\10\1\212\2\10\1\0\2\10\1\0\1\10"+ - "\4\212\1\103\1\0\1\104\5\0\4\10\1\213\11\10"+ - "\27\0\7\10\1\212\1\10\2\0\4\10\1\212\2\10"+ - "\1\0\2\10\1\0\1\10\4\212\1\103\1\0\1\104"+ - "\5\0\4\10\1\212\11\10\27\0\6\10\1\132\1\212"+ - "\1\133\2\0\4\10\1\212\2\10\1\0\2\10\1\0"+ - "\1\10\4\212\1\103\1\0\1\104\5\0\4\10\1\212"+ - "\11\10\26\0\13\214\1\0\20\214\1\215\1\216\4\214"+ - "\1\0\45\214\13\217\1\0\21\217\1\220\1\221\3\217"+ - "\1\0\45\217\1\0\7\10\1\212\1\10\2\0\4\10"+ - "\1\212\2\10\1\0\1\147\1\10\1\0\1\10\4\212"+ - "\1\103\1\0\1\104\5\0\1\150\3\10\1\212\11\10"+ - "\40\0\1\222\24\0\1\223\2\0\1\224\46\0\1\107"+ - "\1\110\1\107\1\0\1\107\3\0\1\114\7\0\1\114"+ - "\1\0\1\115\2\116\1\0\1\117\61\0\3\110\1\0"+ - "\1\110\15\0\1\115\2\116\1\0\1\117\61\0\5\225"+ - "\2\0\1\225\4\0\1\225\2\0\1\225\3\0\2\225"+ - "\2\0\2\225\12\0\1\225\1\0\1\225\42\0\1\226"+ - "\1\0\1\226\1\0\1\226\103\0\1\227\3\0\1\227"+ - "\103\0\3\115\1\0\1\115\16\0\2\116\1\0\1\117"+ - "\61\0\3\230\1\0\1\230\20\0\1\231\33\0\1\231"+ - "\26\0\11\10\2\0\7\10\1\0\2\10\1\0\5\10"+ - "\10\0\4\10\1\232\11\10\27\0\6\10\1\233\2\10"+ + "\1\163\107\0\1\164\1\165\106\0\1\166\107\0\1\167"+ + "\2\0\1\170\104\0\1\171\107\0\1\172\107\0\1\173"+ + "\107\0\1\174\107\0\1\175\7\0\1\176\77\0\1\177"+ + "\7\0\1\200\1\201\76\0\1\202\34\0\1\203\7\0"+ + "\1\203\7\0\4\203\1\75\1\0\1\76\11\0\1\203"+ + "\37\0\13\74\1\0\26\74\1\0\45\74\13\204\1\0"+ + "\20\204\1\205\1\206\4\204\1\207\45\204\13\210\1\0"+ + "\21\210\1\211\1\212\3\210\1\207\45\210\1\0\7\10"+ + "\1\213\1\10\2\0\4\10\1\213\2\10\1\0\2\10"+ + "\1\0\1\10\4\213\1\103\1\0\1\104\5\0\4\10"+ + "\1\214\11\10\27\0\7\10\1\213\1\10\2\0\4\10"+ + "\1\213\2\10\1\0\2\10\1\0\1\10\4\213\1\103"+ + "\1\0\1\104\5\0\4\10\1\213\11\10\27\0\6\10"+ + "\1\132\1\213\1\133\2\0\4\10\1\213\2\10\1\0"+ + "\2\10\1\0\1\10\4\213\1\103\1\0\1\104\5\0"+ + "\4\10\1\213\11\10\26\0\13\215\1\0\20\215\1\216"+ + "\1\217\4\215\1\0\45\215\13\220\1\0\21\220\1\221"+ + "\1\222\3\220\1\0\45\220\1\0\7\10\1\213\1\10"+ + "\2\0\4\10\1\213\2\10\1\0\1\147\1\10\1\0"+ + "\1\10\4\213\1\103\1\0\1\104\5\0\1\150\3\10"+ + "\1\213\11\10\40\0\1\223\24\0\1\224\2\0\1\225"+ + "\46\0\1\107\1\110\1\107\1\0\1\107\3\0\1\114"+ + "\7\0\1\114\1\0\1\115\2\116\1\0\1\117\61\0"+ + "\3\110\1\0\1\110\15\0\1\115\2\116\1\0\1\117"+ + "\61\0\5\226\2\0\1\226\4\0\1\226\2\0\1\226"+ + "\3\0\2\226\2\0\2\226\12\0\1\226\1\0\1\226"+ + "\42\0\1\227\1\0\1\227\1\0\1\227\103\0\1\230"+ + "\3\0\1\230\103\0\3\115\1\0\1\115\16\0\2\116"+ + "\1\0\1\117\61\0\3\231\1\0\1\231\20\0\1\232"+ + "\33\0\1\232\26\0\11\10\2\0\7\10\1\0\2\10"+ + "\1\0\5\10\10\0\4\10\1\233\11\10\27\0\6\10"+ + "\1\234\2\10\2\0\7\10\1\0\2\10\1\0\5\10"+ + "\10\0\16\10\27\0\11\10\2\0\7\10\1\0\2\10"+ + "\1\0\5\10\10\0\1\10\1\235\14\10\27\0\7\10"+ + "\1\236\1\10\2\0\4\10\1\236\2\10\1\0\2\10"+ + "\1\0\1\10\4\236\1\22\1\0\1\24\5\0\4\10"+ + "\1\236\11\10\27\0\7\10\1\236\1\10\2\0\4\10"+ + "\1\236\2\10\1\0\1\237\1\10\1\0\1\10\4\236"+ + "\1\22\1\0\1\24\5\0\4\10\1\236\11\10\27\0"+ + "\11\10\2\0\7\10\1\0\2\10\1\0\5\10\10\0"+ + "\12\10\1\240\3\10\27\0\11\10\2\0\7\10\1\0"+ + "\2\10\1\0\1\10\1\241\3\10\10\0\16\10\27\0"+ + "\11\10\2\0\7\10\1\0\2\10\1\0\5\10\10\0"+ + "\3\10\1\242\3\10\1\243\6\10\27\0\11\10\2\0"+ + "\7\10\1\0\2\10\1\0\5\10\10\0\1\10\1\244"+ + "\14\10\27\0\11\10\2\0\7\10\1\0\2\10\1\0"+ + "\5\10\10\0\1\245\15\10\26\0\13\134\1\0\20\134"+ + "\1\246\1\136\4\134\1\137\45\134\34\0\1\247\1\250"+ + "\1\0\2\251\1\0\2\137\44\0\110\134\13\140\1\0"+ + "\21\140\1\141\1\246\3\140\1\137\155\140\35\0\1\250"+ + "\1\252\2\251\1\0\2\137\45\0\11\10\2\0\7\10"+ + "\1\0\2\10\1\0\5\10\10\0\2\10\1\253\13\10"+ + "\27\0\11\10\2\0\7\10\1\0\2\10\1\0\5\10"+ + "\10\0\3\10\1\254\12\10\27\0\11\10\2\0\7\10"+ + "\1\0\2\10\1\0\5\10\10\0\5\10\1\255\10\10"+ + "\27\0\3\10\1\256\4\10\1\257\2\0\7\10\1\0"+ + "\2\10\1\0\5\10\10\0\16\10\27\0\11\10\2\0"+ + "\7\10\1\0\2\10\1\0\5\10\10\0\5\10\1\260"+ + "\10\10\27\0\11\10\2\0\7\10\1\0\2\10\1\0"+ + "\5\10\10\0\7\10\1\261\6\10\27\0\11\10\2\0"+ + "\7\10\1\0\2\10\1\0\5\10\10\0\11\10\1\262"+ + "\4\10\27\0\11\10\2\0\7\10\1\0\2\10\1\0"+ + "\5\10\10\0\10\10\1\263\5\10\27\0\11\10\2\0"+ + "\7\10\1\0\2\10\1\0\5\10\10\0\3\10\1\264"+ + "\12\10\27\0\11\10\2\0\7\10\1\0\1\265\1\10"+ + "\1\0\5\10\10\0\16\10\27\0\6\10\1\266\2\10"+ "\2\0\7\10\1\0\2\10\1\0\5\10\10\0\16\10"+ "\27\0\11\10\2\0\7\10\1\0\2\10\1\0\5\10"+ - "\10\0\1\10\1\234\14\10\27\0\7\10\1\235\1\10"+ - "\2\0\4\10\1\235\2\10\1\0\2\10\1\0\1\10"+ - "\4\235\1\22\1\0\1\24\5\0\4\10\1\235\11\10"+ - "\27\0\7\10\1\235\1\10\2\0\4\10\1\235\2\10"+ - "\1\0\1\236\1\10\1\0\1\10\4\235\1\22\1\0"+ - "\1\24\5\0\4\10\1\235\11\10\27\0\11\10\2\0"+ - "\7\10\1\0\2\10\1\0\5\10\10\0\12\10\1\237"+ - "\3\10\27\0\11\10\2\0\7\10\1\0\2\10\1\0"+ - "\1\10\1\240\3\10\10\0\16\10\27\0\11\10\2\0"+ - "\7\10\1\0\2\10\1\0\5\10\10\0\3\10\1\241"+ - "\3\10\1\242\6\10\27\0\11\10\2\0\7\10\1\0"+ - "\2\10\1\0\5\10\10\0\1\10\1\243\14\10\27\0"+ + "\10\0\7\10\1\267\6\10\111\0\1\270\107\0\1\271"+ + "\107\0\1\272\107\0\1\273\34\0\1\274\7\0\1\274"+ + "\7\0\4\274\1\75\1\0\1\76\11\0\1\274\37\0"+ + "\13\204\1\0\20\204\1\275\1\206\4\204\1\207\45\204"+ + "\34\0\1\276\1\277\1\0\2\300\1\0\2\207\44\0"+ + "\110\204\13\210\1\0\21\210\1\211\1\275\3\210\1\207"+ + "\155\210\35\0\1\277\1\301\2\300\1\0\2\207\45\0"+ + "\7\10\1\302\1\10\2\0\4\10\1\302\2\10\1\0"+ + "\2\10\1\0\1\10\4\302\1\103\1\0\1\104\5\0"+ + "\4\10\1\302\11\10\27\0\7\10\1\302\1\10\2\0"+ + "\4\10\1\302\2\10\1\0\1\237\1\10\1\0\1\10"+ + "\4\302\1\103\1\0\1\104\5\0\4\10\1\302\11\10"+ + "\26\0\13\215\1\0\20\215\1\303\1\217\4\215\1\0"+ + "\45\215\34\0\1\304\53\0\110\215\13\220\1\0\21\220"+ + "\1\221\1\303\3\220\1\0\155\220\36\0\1\305\51\0"+ + "\13\223\1\0\26\223\1\225\45\223\1\0\5\226\2\0"+ + "\1\226\1\114\3\0\1\226\2\0\1\226\1\114\2\0"+ + "\2\226\2\0\2\226\12\0\1\226\1\0\1\226\42\0"+ + "\1\227\1\0\1\227\1\0\1\227\3\0\1\114\7\0"+ + "\1\114\67\0\1\230\3\0\1\230\3\0\1\114\7\0"+ + "\1\114\67\0\3\231\1\0\1\231\21\0\1\117\61\0"+ + "\3\231\1\0\1\231\103\0\11\10\2\0\7\10\1\0"+ + "\2\10\1\0\5\10\10\0\12\10\1\306\3\10\27\0"+ "\11\10\2\0\7\10\1\0\2\10\1\0\5\10\10\0"+ - "\1\244\15\10\26\0\13\134\1\0\20\134\1\245\1\136"+ - "\4\134\1\137\45\134\34\0\1\246\1\247\1\0\2\250"+ - "\1\0\2\137\44\0\110\134\13\140\1\0\21\140\1\141"+ - "\1\245\3\140\1\137\155\140\35\0\1\247\1\251\2\250"+ - "\1\0\2\137\45\0\11\10\2\0\7\10\1\0\2\10"+ - "\1\0\5\10\10\0\2\10\1\252\13\10\27\0\11\10"+ - "\2\0\7\10\1\0\2\10\1\0\5\10\10\0\3\10"+ - "\1\253\12\10\27\0\11\10\2\0\7\10\1\0\2\10"+ - "\1\0\5\10\10\0\5\10\1\254\10\10\27\0\3\10"+ - "\1\255\4\10\1\256\2\0\7\10\1\0\2\10\1\0"+ - "\5\10\10\0\16\10\27\0\11\10\2\0\7\10\1\0"+ - "\2\10\1\0\5\10\10\0\5\10\1\257\10\10\27\0"+ + "\1\307\15\10\27\0\11\10\2\0\7\10\1\0\2\10"+ + "\1\0\5\10\1\310\1\0\1\311\5\0\16\10\27\0"+ "\11\10\2\0\7\10\1\0\2\10\1\0\5\10\10\0"+ - "\7\10\1\260\6\10\27\0\11\10\2\0\7\10\1\0"+ - "\2\10\1\0\5\10\10\0\11\10\1\261\4\10\27\0"+ - "\11\10\2\0\7\10\1\0\2\10\1\0\5\10\10\0"+ - "\10\10\1\262\5\10\27\0\11\10\2\0\7\10\1\0"+ - "\2\10\1\0\5\10\10\0\3\10\1\263\12\10\27\0"+ - "\11\10\2\0\7\10\1\0\1\264\1\10\1\0\5\10"+ - "\10\0\16\10\27\0\6\10\1\265\2\10\2\0\7\10"+ + "\1\312\15\10\27\0\7\10\1\313\1\10\2\0\7\10"+ "\1\0\2\10\1\0\5\10\10\0\16\10\27\0\11\10"+ - "\2\0\7\10\1\0\2\10\1\0\5\10\10\0\7\10"+ - "\1\266\6\10\111\0\1\267\107\0\1\270\107\0\1\271"+ - "\107\0\1\272\34\0\1\273\7\0\1\273\7\0\4\273"+ - "\1\75\1\0\1\76\11\0\1\273\37\0\13\203\1\0"+ - "\20\203\1\274\1\205\4\203\1\206\45\203\34\0\1\275"+ - "\1\276\1\0\2\277\1\0\2\206\44\0\110\203\13\207"+ - "\1\0\21\207\1\210\1\274\3\207\1\206\155\207\35\0"+ - "\1\276\1\300\2\277\1\0\2\206\45\0\7\10\1\301"+ - "\1\10\2\0\4\10\1\301\2\10\1\0\2\10\1\0"+ - "\1\10\4\301\1\103\1\0\1\104\5\0\4\10\1\301"+ - "\11\10\27\0\7\10\1\301\1\10\2\0\4\10\1\301"+ - "\2\10\1\0\1\236\1\10\1\0\1\10\4\301\1\103"+ - "\1\0\1\104\5\0\4\10\1\301\11\10\26\0\13\214"+ - "\1\0\20\214\1\302\1\216\4\214\1\0\45\214\34\0"+ - "\1\303\53\0\110\214\13\217\1\0\21\217\1\220\1\302"+ - "\3\217\1\0\155\217\36\0\1\304\51\0\13\222\1\0"+ - "\26\222\1\224\45\222\1\0\5\225\2\0\1\225\1\114"+ - "\3\0\1\225\2\0\1\225\1\114\2\0\2\225\2\0"+ - "\2\225\12\0\1\225\1\0\1\225\42\0\1\226\1\0"+ - "\1\226\1\0\1\226\3\0\1\114\7\0\1\114\67\0"+ - "\1\227\3\0\1\227\3\0\1\114\7\0\1\114\67\0"+ - "\3\230\1\0\1\230\21\0\1\117\61\0\3\230\1\0"+ - "\1\230\103\0\11\10\2\0\7\10\1\0\2\10\1\0"+ - "\5\10\10\0\12\10\1\305\3\10\27\0\11\10\2\0"+ - "\7\10\1\0\2\10\1\0\5\10\10\0\1\306\15\10"+ + "\2\0\7\10\1\0\1\314\1\10\1\0\5\10\10\0"+ + "\16\10\27\0\11\10\2\0\7\10\1\0\1\315\1\10"+ + "\1\0\5\10\10\0\16\10\27\0\3\10\1\316\5\10"+ + "\2\0\7\10\1\0\2\10\1\0\5\10\10\0\16\10"+ "\27\0\11\10\2\0\7\10\1\0\2\10\1\0\5\10"+ - "\1\307\1\0\1\310\5\0\16\10\27\0\11\10\2\0"+ - "\7\10\1\0\2\10\1\0\5\10\10\0\1\311\15\10"+ - "\27\0\7\10\1\312\1\10\2\0\7\10\1\0\2\10"+ - "\1\0\5\10\10\0\16\10\27\0\11\10\2\0\7\10"+ - "\1\0\1\313\1\10\1\0\5\10\10\0\16\10\27\0"+ - "\11\10\2\0\7\10\1\0\1\314\1\10\1\0\5\10"+ - "\10\0\16\10\27\0\3\10\1\315\5\10\2\0\7\10"+ - "\1\0\2\10\1\0\5\10\10\0\16\10\27\0\11\10"+ - "\2\0\7\10\1\0\2\10\1\0\5\10\10\0\5\10"+ - "\1\316\10\10\27\0\11\10\2\0\7\10\1\0\2\10"+ - "\1\0\5\10\10\0\3\10\1\317\12\10\63\0\1\247"+ - "\1\0\2\250\1\0\2\137\44\0\34\246\1\320\1\321"+ - "\52\246\35\251\1\322\1\323\51\251\1\0\11\10\2\0"+ - "\7\10\1\0\1\324\1\10\1\0\5\10\10\0\16\10"+ - "\27\0\11\10\2\0\7\10\1\0\2\10\1\0\4\10"+ - "\1\325\10\0\16\10\27\0\11\10\2\0\7\10\1\0"+ - "\2\10\1\0\5\10\10\0\3\10\1\326\12\10\27\0"+ - "\6\10\1\327\2\10\2\0\7\10\1\0\2\10\1\0"+ - "\5\10\10\0\16\10\27\0\11\10\2\0\7\10\1\0"+ - "\2\10\1\0\5\10\10\0\3\10\1\330\12\10\27\0"+ - "\10\10\1\331\2\0\7\10\1\0\2\10\1\0\5\10"+ - "\10\0\16\10\27\0\7\10\1\332\1\10\2\0\7\10"+ - "\1\0\2\10\1\0\5\10\10\0\16\10\27\0\10\10"+ - "\1\333\2\0\7\10\1\0\2\10\1\0\5\10\10\0"+ - "\16\10\62\0\1\334\1\0\1\335\106\0\1\276\1\0"+ - "\2\277\1\0\2\206\44\0\34\275\1\336\1\337\52\275"+ - "\35\300\1\340\1\341\51\300\1\0\11\10\2\0\7\10"+ - "\1\0\2\10\1\0\5\10\1\342\1\0\1\343\5\0"+ - "\16\10\26\0\34\303\1\344\1\345\52\303\35\304\1\346"+ - "\1\347\51\304\1\0\10\10\1\350\2\0\7\10\1\0"+ - "\2\10\1\0\5\10\10\0\16\10\62\0\1\351\111\0"+ - "\1\352\52\0\11\10\2\0\7\10\1\0\2\10\1\0"+ - "\5\10\10\0\6\10\1\353\7\10\27\0\11\10\2\0"+ - "\7\10\1\0\2\10\1\0\5\10\10\0\2\10\1\354"+ - "\13\10\27\0\11\10\2\0\7\10\1\0\2\10\1\0"+ - "\5\10\10\0\10\10\1\355\5\10\27\0\11\10\2\0"+ - "\7\10\1\0\2\10\1\0\5\10\10\0\7\10\1\356"+ - "\6\10\27\0\11\10\2\0\7\10\1\0\2\10\1\0"+ - "\5\10\10\0\3\10\1\357\12\10\26\0\34\246\1\360"+ - "\1\361\162\246\145\251\1\362\1\363\51\251\1\0\11\10"+ - "\2\0\7\10\1\0\2\10\1\0\5\10\10\0\4\10"+ - "\1\364\11\10\27\0\11\10\2\0\7\10\1\0\2\10"+ - "\1\0\5\10\10\0\4\10\1\365\11\10\27\0\11\10"+ - "\2\0\7\10\1\0\1\366\1\10\1\0\5\10\10\0"+ - "\16\10\27\0\11\10\2\0\7\10\1\0\2\10\1\0"+ - "\5\10\10\0\4\10\1\367\11\10\27\0\11\10\2\0"+ - "\7\10\1\0\2\10\1\0\5\10\10\0\2\10\1\370"+ - "\13\10\27\0\11\10\2\0\7\10\1\0\2\10\1\0"+ - "\5\10\10\0\1\371\15\10\27\0\11\10\2\0\7\10"+ - "\1\0\1\372\1\10\1\0\5\10\10\0\16\10\62\0"+ - "\1\373\111\0\1\374\51\0\34\275\1\375\1\376\162\275"+ - "\145\300\1\377\1\u0100\51\300\34\0\1\u0101\111\0\1\u0102"+ - "\51\0\34\303\1\u0103\1\u0104\162\303\145\304\1\u0105\1\u0106"+ - "\51\304\1\0\10\10\1\u0107\2\0\7\10\1\0\2\10"+ - "\1\0\5\10\10\0\16\10\62\0\1\246\111\0\1\251"+ - "\52\0\11\10\2\0\7\10\1\0\2\10\1\0\5\10"+ - "\10\0\1\u0108\15\10\27\0\11\10\2\0\7\10\1\0"+ - "\2\10\1\0\5\10\10\0\5\10\1\u0109\10\10\27\0"+ + "\10\0\5\10\1\317\10\10\27\0\11\10\2\0\7\10"+ + "\1\0\2\10\1\0\5\10\10\0\3\10\1\320\12\10"+ + "\63\0\1\250\1\0\2\251\1\0\2\137\44\0\34\247"+ + "\1\321\1\322\52\247\35\252\1\323\1\324\51\252\1\0"+ + "\11\10\2\0\7\10\1\0\1\325\1\10\1\0\5\10"+ + "\10\0\16\10\27\0\11\10\2\0\7\10\1\0\2\10"+ + "\1\0\4\10\1\326\10\0\16\10\27\0\11\10\2\0"+ + "\7\10\1\0\2\10\1\0\5\10\10\0\3\10\1\327"+ + "\12\10\27\0\6\10\1\330\2\10\2\0\7\10\1\0"+ + "\2\10\1\0\5\10\10\0\16\10\27\0\11\10\2\0"+ + "\7\10\1\0\2\10\1\0\5\10\10\0\3\10\1\331"+ + "\12\10\27\0\10\10\1\332\2\0\7\10\1\0\2\10"+ + "\1\0\5\10\10\0\16\10\27\0\7\10\1\333\1\10"+ + "\2\0\7\10\1\0\2\10\1\0\5\10\10\0\16\10"+ + "\27\0\10\10\1\334\2\0\7\10\1\0\2\10\1\0"+ + "\5\10\10\0\16\10\62\0\1\335\1\0\1\336\106\0"+ + "\1\277\1\0\2\300\1\0\2\207\44\0\34\276\1\337"+ + "\1\340\52\276\35\301\1\341\1\342\51\301\1\0\11\10"+ + "\2\0\7\10\1\0\2\10\1\0\5\10\1\343\1\0"+ + "\1\344\5\0\16\10\26\0\34\304\1\345\1\346\52\304"+ + "\35\305\1\347\1\350\51\305\1\0\10\10\1\351\2\0"+ + "\7\10\1\0\2\10\1\0\5\10\10\0\16\10\62\0"+ + "\1\352\111\0\1\353\52\0\11\10\2\0\7\10\1\0"+ + "\2\10\1\0\5\10\10\0\6\10\1\354\7\10\27\0"+ "\11\10\2\0\7\10\1\0\2\10\1\0\5\10\10\0"+ - "\1\10\1\u010a\14\10\26\0\34\246\1\u010b\1\361\106\246"+ - "\1\u010c\1\361\52\246\35\251\1\362\1\u010d\106\251\1\362"+ - "\1\u010b\51\251\1\0\11\10\2\0\7\10\1\0\2\10"+ - "\1\0\5\10\10\0\5\10\1\u010e\10\10\27\0\11\10"+ - "\2\0\7\10\1\0\2\10\1\0\5\10\10\0\1\10"+ - "\1\u010f\14\10\27\0\11\10\2\0\7\10\1\0\2\10"+ - "\1\0\5\10\10\0\5\10\1\u0110\10\10\27\0\10\10"+ - "\1\u0111\2\0\7\10\1\0\2\10\1\0\5\10\10\0"+ - "\16\10\62\0\1\275\111\0\1\300\51\0\34\275\1\u0112"+ - "\1\376\106\275\1\u0113\1\376\52\275\35\300\1\377\1\u0114"+ - "\106\300\1\377\1\u0112\51\300\34\303\1\u0115\1\u0104\106\303"+ - "\1\u0116\1\u0104\52\303\35\304\1\u0105\1\u0117\106\304\1\u0105"+ - "\1\u0115\51\304\1\0\11\10\2\0\7\10\1\0\2\10"+ - "\1\0\5\10\10\0\11\10\1\u0118\4\10\27\0\11\10"+ - "\2\0\7\10\1\0\2\10\1\0\4\10\1\u0119\10\0"+ - "\16\10\63\0\1\u011a\1\0\2\u011b\1\0\2\u011c\44\0"+ - "\34\246\1\u011d\1\361\52\246\35\251\1\362\1\u011e\51\251"+ - "\34\275\1\u011f\1\376\52\275\35\300\1\377\1\u0120\51\300"+ - "\34\303\1\u0121\1\u0104\52\303\35\304\1\u0105\1\u0122\51\304"+ - "\1\0\11\10\2\0\7\10\1\0\1\u0123\1\10\1\0"+ - "\5\10\10\0\16\10\26\0\34\246\1\u0124\1\361\52\246"+ - "\35\251\1\362\1\u0125\51\251\34\275\1\u0126\1\376\52\275"+ - "\35\300\1\377\1\u0127\51\300\34\303\1\u0128\1\u0104\52\303"+ - "\35\304\1\u0105\1\u0129\51\304"; + "\2\10\1\355\13\10\27\0\11\10\2\0\7\10\1\0"+ + "\2\10\1\0\5\10\10\0\10\10\1\356\5\10\27\0"+ + "\11\10\2\0\7\10\1\0\2\10\1\0\5\10\10\0"+ + "\7\10\1\357\6\10\27\0\11\10\2\0\7\10\1\0"+ + "\2\10\1\0\5\10\10\0\3\10\1\360\12\10\26\0"+ + "\34\247\1\361\1\362\162\247\145\252\1\363\1\364\51\252"+ + "\1\0\11\10\2\0\7\10\1\0\2\10\1\0\5\10"+ + "\10\0\4\10\1\365\11\10\27\0\11\10\2\0\7\10"+ + "\1\0\2\10\1\0\5\10\10\0\4\10\1\366\11\10"+ + "\27\0\11\10\2\0\7\10\1\0\1\367\1\10\1\0"+ + "\5\10\10\0\16\10\27\0\11\10\2\0\7\10\1\0"+ + "\2\10\1\0\5\10\10\0\4\10\1\370\11\10\27\0"+ + "\11\10\2\0\7\10\1\0\2\10\1\0\5\10\10\0"+ + "\2\10\1\371\13\10\27\0\11\10\2\0\7\10\1\0"+ + "\2\10\1\0\5\10\10\0\1\372\15\10\27\0\11\10"+ + "\2\0\7\10\1\0\1\373\1\10\1\0\5\10\10\0"+ + "\16\10\62\0\1\374\111\0\1\375\51\0\34\276\1\376"+ + "\1\377\162\276\145\301\1\u0100\1\u0101\51\301\34\0\1\u0102"+ + "\111\0\1\u0103\51\0\34\304\1\u0104\1\u0105\162\304\145\305"+ + "\1\u0106\1\u0107\51\305\1\0\10\10\1\u0108\2\0\7\10"+ + "\1\0\2\10\1\0\5\10\10\0\16\10\62\0\1\247"+ + "\111\0\1\252\52\0\11\10\2\0\7\10\1\0\2\10"+ + "\1\0\5\10\10\0\1\u0109\15\10\27\0\11\10\2\0"+ + "\7\10\1\0\2\10\1\0\5\10\10\0\5\10\1\u010a"+ + "\10\10\27\0\11\10\2\0\7\10\1\0\2\10\1\0"+ + "\5\10\10\0\1\10\1\u010b\14\10\26\0\34\247\1\u010c"+ + "\1\362\106\247\1\u010d\1\362\52\247\35\252\1\363\1\u010e"+ + "\106\252\1\363\1\u010c\51\252\1\0\11\10\2\0\7\10"+ + "\1\0\2\10\1\0\5\10\10\0\5\10\1\u010f\10\10"+ + "\27\0\11\10\2\0\7\10\1\0\2\10\1\0\5\10"+ + "\10\0\1\10\1\u0110\14\10\27\0\11\10\2\0\7\10"+ + "\1\0\2\10\1\0\5\10\10\0\5\10\1\u0111\10\10"+ + "\27\0\10\10\1\u0112\2\0\7\10\1\0\2\10\1\0"+ + "\5\10\10\0\16\10\62\0\1\276\111\0\1\301\51\0"+ + "\34\276\1\u0113\1\377\106\276\1\u0114\1\377\52\276\35\301"+ + "\1\u0100\1\u0115\106\301\1\u0100\1\u0113\51\301\34\304\1\u0116"+ + "\1\u0105\106\304\1\u0117\1\u0105\52\304\35\305\1\u0106\1\u0118"+ + "\106\305\1\u0106\1\u0116\51\305\1\0\11\10\2\0\7\10"+ + "\1\0\2\10\1\0\5\10\10\0\11\10\1\u0119\4\10"+ + "\27\0\11\10\2\0\7\10\1\0\2\10\1\0\4\10"+ + "\1\u011a\10\0\16\10\63\0\1\u011b\1\0\2\u011c\1\0"+ + "\2\u011d\44\0\34\247\1\u011e\1\362\52\247\35\252\1\363"+ + "\1\u011f\51\252\34\276\1\u0120\1\377\52\276\35\301\1\u0100"+ + "\1\u0121\51\301\34\304\1\u0122\1\u0105\52\304\35\305\1\u0106"+ + "\1\u0123\51\305\1\0\11\10\2\0\7\10\1\0\1\u0124"+ + "\1\10\1\0\5\10\10\0\16\10\26\0\34\247\1\u0125"+ + "\1\362\52\247\35\252\1\363\1\u0126\51\252\34\276\1\u0127"+ + "\1\377\52\276\35\301\1\u0100\1\u0128\51\301\34\304\1\u0129"+ + "\1\u0105\52\304\35\305\1\u0106\1\u012a\51\305"; private static int [] zzUnpackTrans() { - int [] result = new int[15120]; + int [] result = new int[15192]; int offset = 0; offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); return result; @@ -608,9 +675,9 @@ class _PythonLexer implements FlexLexer { private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); private static final String ZZ_ATTRIBUTE_PACKED_0 = - "\3\0\1\11\16\1\1\11\1\1\5\11\25\1\14\11"+ + "\3\0\1\11\16\1\1\11\1\1\5\11\26\1\13\11"+ "\4\1\1\11\10\1\4\0\1\11\1\1\1\0\1\11"+ - "\11\1\1\11\5\1\1\11\22\1\3\11\1\1\1\11"+ + "\11\1\1\11\5\1\1\11\22\1\3\11\1\1\2\11"+ "\1\1\5\11\1\1\2\11\1\1\1\11\1\0\3\1"+ "\1\11\13\1\2\0\1\11\4\1\1\0\15\1\1\11"+ "\1\0\16\1\4\11\1\0\2\1\1\11\1\0\2\1"+ @@ -620,7 +687,7 @@ class _PythonLexer implements FlexLexer { "\1\11\4\1\1\11\1\0\1\11\6\0\7\1"; private static int [] zzUnpackAttribute() { - int [] result = new int[297]; + int [] result = new int[298]; int offset = 0; offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); return result; @@ -713,7 +780,7 @@ return yylength()-s.length(); char [] map = new char[0x10000]; int i = 0; /* index in packed string */ int j = 0; /* index in unpacked array */ - while (i < 3338) { + while (i < 4678) { int count = packed.charAt(i++); char value = packed.charAt(i++); do map[j++] = value; while (--count > 0); @@ -935,410 +1002,414 @@ return yylength()-s.length(); zzMarkedPos = zzMarkedPosL; switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { - case 89: + case 90: { return PyTokenTypes.YIELD_KEYWORD; } - case 100: break; - case 84: + case 101: break; + case 85: { yypushback(getSpaceLength(yytext())); if (zzCurrentPos != 0) return PyTokenTypes.TRIPLE_QUOTED_STRING; yybegin(PENDING_DOCSTRING); return PyTokenTypes.DOCSTRING; } - case 101: break; + case 102: break; case 2: { return PyTokenTypes.INTEGER_LITERAL; } - case 102: break; - case 17: - { return PyTokenTypes.DIV; - } case 103: break; case 18: - { return PyTokenTypes.PERC; + { return PyTokenTypes.DIV; } case 104: break; + case 19: + { return PyTokenTypes.PERC; + } + case 105: break; case 8: { return PyTokenTypes.BACKSLASH; } - case 105: break; - case 26: + case 106: break; + case 27: { return PyTokenTypes.RPAR; } - case 106: break; + case 107: break; case 1: { return PyTokenTypes.BAD_CHARACTER; } - case 107: break; - case 29: + case 108: break; + case 30: { return PyTokenTypes.LBRACE; } - case 108: break; - case 35: - { yypushback(1); yybegin(YYINITIAL); - } case 109: break; - case 71: + case 72: { yybegin(IN_DOCSTRING_OWNER); return PyTokenTypes.DEF_KEYWORD; } case 110: break; - case 87: - { yybegin(IN_DOCSTRING_OWNER); return PyTokenTypes.CLASS_KEYWORD; + case 35: + { yypushback(1); yybegin(YYINITIAL); } case 111: break; - case 79: - { yypushback(getSpaceLength(yytext())); return PyTokenTypes.DOCSTRING; + case 88: + { yybegin(IN_DOCSTRING_OWNER); return PyTokenTypes.CLASS_KEYWORD; } case 112: break; + case 80: + { yypushback(getSpaceLength(yytext())); return PyTokenTypes.DOCSTRING; + } + case 113: break; case 6: { return PyTokenTypes.MINUS; } - case 113: break; + case 114: break; case 7: { if (zzInput == YYEOF && zzStartRead == 0) return PyTokenTypes.DOCSTRING; else return PyTokenTypes.SINGLE_QUOTED_STRING; } - case 114: break; - case 86: + case 115: break; + case 87: { return PyTokenTypes.BREAK_KEYWORD; } - case 115: break; - case 28: + case 116: break; + case 29: { return PyTokenTypes.RBRACKET; } - case 116: break; - case 64: + case 117: break; + case 65: { yypushback(getSpaceLength(yytext())); yybegin(YYINITIAL); return PyTokenTypes.DOCSTRING; } - case 117: break; + case 118: break; case 5: { return PyTokenTypes.DOT; } - case 118: break; + case 119: break; case 3: { return PyTokenTypes.IDENTIFIER; } - case 119: break; - case 25: + case 120: break; + case 26: { return PyTokenTypes.LPAR; } - case 120: break; - case 23: + case 121: break; + case 24: { return PyTokenTypes.LT; } - case 121: break; + case 122: break; case 46: { return PyTokenTypes.IN_KEYWORD; } - case 122: break; - case 88: + case 123: break; + case 89: { return PyTokenTypes.RAISE_KEYWORD; } - case 123: break; - case 76: + case 124: break; + case 77: { return PyTokenTypes.GTGTEQ; } - case 124: break; + case 125: break; case 9: { return PyTokenTypes.SPACE; } - case 125: break; - case 92: + case 126: break; + case 93: { return PyTokenTypes.EXCEPT_KEYWORD; } - case 126: break; + case 127: break; case 41: { return PyTokenTypes.IMAGINARY_LITERAL; } - case 127: break; + case 128: break; case 39: { return PyTokenTypes.SINGLE_QUOTED_STRING; } - case 128: break; + case 129: break; case 11: { return PyTokenTypes.FORMFEED; } - case 129: break; + case 130: break; case 13: { return PyTokenTypes.SEMICOLON; } - case 130: break; - case 22: + case 131: break; + case 23: { return PyTokenTypes.GT; } - case 131: break; - case 27: + case 132: break; + case 28: { return PyTokenTypes.LBRACKET; } - case 132: break; + case 133: break; case 33: { return PyTokenTypes.COLON; } - case 133: break; - case 77: + case 134: break; + case 78: { return PyTokenTypes.LTLTEQ; } - case 134: break; - case 82: - { return PyTokenTypes.ELSE_KEYWORD; - } case 135: break; - case 20: - { return PyTokenTypes.OR; + case 52: + { return PyTokenTypes.ATEQ; } case 136: break; - case 68: + case 83: + { return PyTokenTypes.ELSE_KEYWORD; + } + case 137: break; + case 21: + { return PyTokenTypes.OR; + } + case 138: break; + case 69: { yypushback(getSpaceLength(yytext())); if (zzCurrentPos != 0) return PyTokenTypes.SINGLE_QUOTED_STRING; yybegin(PENDING_DOCSTRING); return PyTokenTypes.DOCSTRING; } - case 137: break; - case 67: + case 139: break; + case 68: { if (zzInput == YYEOF && zzStartRead == 0) return PyTokenTypes.DOCSTRING; else return PyTokenTypes.TRIPLE_QUOTED_STRING; } - case 138: break; + case 140: break; case 50: { return PyTokenTypes.MULTEQ; } - case 139: break; - case 97: + case 141: break; + case 98: { return PyTokenTypes.FINALLY_KEYWORD; } - case 140: break; - case 90: + case 142: break; + case 91: { return PyTokenTypes.WHILE_KEYWORD; } - case 141: break; + case 143: break; case 16: { return PyTokenTypes.MULT; } - case 142: break; - case 93: + case 144: break; + case 94: { return PyTokenTypes.ASSERT_KEYWORD; } - case 143: break; - case 53: + case 145: break; + case 54: { return PyTokenTypes.FLOORDIV; } - case 144: break; - case 96: + case 146: break; + case 97: { return PyTokenTypes.GLOBAL_KEYWORD; } - case 145: break; + case 147: break; case 37: { if (zzInput == YYEOF) return PyTokenTypes.DOCSTRING; else yybegin(YYINITIAL); return PyTokenTypes.SINGLE_QUOTED_STRING; } - case 146: break; - case 91: + case 148: break; + case 92: { return PyTokenTypes.LAMBDA_KEYWORD; } - case 147: break; - case 57: + case 149: break; + case 58: { return PyTokenTypes.XOREQ; } - case 148: break; - case 66: + case 150: break; + case 67: { return PyTokenTypes.FOR_KEYWORD; } - case 149: break; - case 31: + case 151: break; + case 17: { return PyTokenTypes.AT; } - case 150: break; - case 70: + case 152: break; + case 71: { return PyTokenTypes.NOT_KEYWORD; } - case 151: break; + case 153: break; case 14: { return PyTokenTypes.PLUS; } - case 152: break; + case 154: break; case 43: { return PyTokenTypes.MINUSEQ; } - case 153: break; - case 63: + case 155: break; + case 64: { return PyTokenTypes.NE; } - case 154: break; + case 156: break; case 32: { return PyTokenTypes.COMMA; } - case 155: break; + case 157: break; case 49: { return PyTokenTypes.EQEQ; } - case 156: break; + case 158: break; case 34: { return PyTokenTypes.TICK; } - case 157: break; + case 159: break; case 51: { return PyTokenTypes.EXP; } - case 158: break; - case 80: + case 160: break; + case 81: { return PyTokenTypes.TRIPLE_QUOTED_STRING; } - case 159: break; - case 99: + case 161: break; + case 100: { return PyTokenTypes.CONTINUE_KEYWORD; } - case 160: break; - case 62: + case 162: break; + case 63: { return PyTokenTypes.LTLT; } - case 161: break; - case 60: + case 163: break; + case 61: { return PyTokenTypes.LE; } - case 162: break; - case 69: + case 164: break; + case 70: { return PyTokenTypes.AND_KEYWORD; } - case 163: break; + case 165: break; case 42: { return PyTokenTypes.OR_KEYWORD; } - case 164: break; + case 166: break; case 4: { if (zzCurrentPos == 0) yybegin(PENDING_DOCSTRING); return PyTokenTypes.END_OF_LINE_COMMENT; } - case 165: break; + case 167: break; case 44: { yypushback(getSpaceLength(yytext())); if (zzCurrentPos != 0) return PyTokenTypes.SINGLE_QUOTED_STRING; return PyTokenTypes.DOCSTRING; } - case 166: break; - case 85: + case 168: break; + case 86: { return PyTokenTypes.PASS_KEYWORD; } - case 167: break; - case 65: + case 169: break; + case 66: { yypushback(yylength()-1); yybegin(PENDING_DOCSTRING); return PyTokenTypes.COLON; } - case 168: break; + case 170: break; case 36: { return PyTokenTypes.END_OF_LINE_COMMENT; } - case 169: break; - case 98: + case 171: break; + case 99: { yypushback(getSpaceLength(yytext())); if (zzCurrentPos != 0) return PyTokenTypes.TRIPLE_QUOTED_STRING; return PyTokenTypes.DOCSTRING; } - case 170: break; - case 56: + case 172: break; + case 57: { return PyTokenTypes.OREQ; } - case 171: break; - case 59: + case 173: break; + case 60: { return PyTokenTypes.GTGT; } - case 172: break; - case 19: + case 174: break; + case 20: { return PyTokenTypes.AND; } - case 173: break; - case 52: + case 175: break; + case 53: { return PyTokenTypes.DIVEQ; } - case 174: break; - case 94: + case 176: break; + case 95: { return PyTokenTypes.RETURN_KEYWORD; } - case 175: break; - case 95: + case 177: break; + case 96: { return PyTokenTypes.IMPORT_KEYWORD; } - case 176: break; - case 58: + case 178: break; + case 59: { return PyTokenTypes.GE; } - case 177: break; + case 179: break; case 48: { return PyTokenTypes.PLUSEQ; } - case 178: break; - case 78: + case 180: break; + case 79: { if (zzInput == YYEOF) return PyTokenTypes.DOCSTRING; else yybegin(YYINITIAL); return PyTokenTypes.TRIPLE_QUOTED_STRING; } - case 179: break; + case 181: break; case 47: { return PyTokenTypes.IS_KEYWORD; } - case 180: break; - case 75: + case 182: break; + case 76: { return PyTokenTypes.FLOORDIVEQ; } - case 181: break; + case 183: break; case 40: { return PyTokenTypes.FLOAT_LITERAL; } - case 182: break; + case 184: break; case 38: { return PyTokenTypes.LINE_BREAK; } - case 183: break; - case 54: - { return PyTokenTypes.PERCEQ; - } - case 184: break; - case 73: - { return PyTokenTypes.TRY_KEYWORD; - } case 185: break; case 55: - { return PyTokenTypes.ANDEQ; + { return PyTokenTypes.PERCEQ; } case 186: break; + case 74: + { return PyTokenTypes.TRY_KEYWORD; + } + case 187: break; + case 56: + { return PyTokenTypes.ANDEQ; + } + case 188: break; case 15: { return PyTokenTypes.EQ; } - case 187: break; - case 81: + case 189: break; + case 82: { return PyTokenTypes.FROM_KEYWORD; } - case 188: break; + case 190: break; case 12: { if (zzCurrentPos == 0) yybegin(PENDING_DOCSTRING); return PyTokenTypes.LINE_BREAK; } - case 189: break; - case 74: + case 191: break; + case 75: { return PyTokenTypes.EXPEQ; } - case 190: break; - case 83: + case 192: break; + case 84: { return PyTokenTypes.ELIF_KEYWORD; } - case 191: break; - case 30: + case 193: break; + case 31: { return PyTokenTypes.RBRACE; } - case 192: break; + case 194: break; case 45: { return PyTokenTypes.IF_KEYWORD; } - case 193: break; + case 195: break; case 10: { return PyTokenTypes.TAB; } - case 194: break; - case 61: + case 196: break; + case 62: { return PyTokenTypes.NE_OLD; } - case 195: break; - case 24: + case 197: break; + case 25: { return PyTokenTypes.TILDE; } - case 196: break; - case 72: + case 198: break; + case 73: { return PyTokenTypes.DEL_KEYWORD; } - case 197: break; - case 21: + case 199: break; + case 22: { return PyTokenTypes.XOR; } - case 198: break; + case 200: break; default: if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { zzAtEOF = true; diff --git a/python/helpers/pydev/pydevd.py b/python/helpers/pydev/pydevd.py index 99e58a00bef1..b2d22bd317e0 100644 --- a/python/helpers/pydev/pydevd.py +++ b/python/helpers/pydev/pydevd.py @@ -380,13 +380,13 @@ class PyDB: return self.plugin def get_project_roots(self): - roots = os.getenv('PYCHARM_PROJECT_ROOTS', '').split(os.pathsep) - pydev_log.debug("PYCHARM_PROJECT_ROOTS %s\n" % roots) - return roots + if self.project_roots is None: + roots = os.getenv('IDE_PROJECT_ROOTS', '').split(os.pathsep) + pydev_log.debug("IDE_PROJECT_ROOTS %s\n" % roots) + self.project_roots = roots def not_in_scope(self, filename): - if self.project_roots is None: - return False + self.get_project_roots() filename = os.path.normcase(filename) for root in self.project_roots: root = os.path.normcase(root) @@ -1140,9 +1140,6 @@ class PyDB: else: exception, notify_always, notify_on_terminate, ignore_libraries = text, 0, 0, 0 - if int(ignore_libraries) > 0 and self.project_roots is None: - self.project_roots = self.get_project_roots() - if exception.find('-') != -1: type, exception = exception.split('-') else: @@ -1545,8 +1542,6 @@ class PyDB: #print('trace_dispatch', base, frame.f_lineno, event, frame.f_code.co_name, is_file_to_ignore) if is_file_to_ignore: if DONT_TRACE[base] == LIB_FILE: - if self.project_roots is None: - self.project_roots = self.get_project_roots() if self.not_in_scope(filename): return None else: diff --git a/python/helpers/pydev/pydevd_breakpoints.py b/python/helpers/pydev/pydevd_breakpoints.py index ab8550f28998..fdd069abcd1e 100644 --- a/python/helpers/pydev/pydevd_breakpoints.py +++ b/python/helpers/pydev/pydevd_breakpoints.py @@ -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 diff --git a/python/helpers/pydev/pydevd_signature.py b/python/helpers/pydev/pydevd_signature.py index d7b37c84cb76..5967ab31786e 100644 --- a/python/helpers/pydev/pydevd_signature.py +++ b/python/helpers/pydev/pydevd_signature.py @@ -31,7 +31,7 @@ class Signature(object): class SignatureFactory(object): def __init__(self): self._caller_cache = {} - self.project_roots = os.getenv('PYCHARM_PROJECT_ROOTS', '').split(os.pathsep) + self.project_roots = os.getenv('IDE_PROJECT_ROOTS', '').split(os.pathsep) def is_in_scope(self, filename): filename = os.path.normcase(filename) diff --git a/python/psi-api/src/com/jetbrains/python/PyNames.java b/python/psi-api/src/com/jetbrains/python/PyNames.java index 20a37449454e..d41d00baed8c 100644 --- a/python/psi-api/src/com/jetbrains/python/PyNames.java +++ b/python/psi-api/src/com/jetbrains/python/PyNames.java @@ -357,8 +357,23 @@ public class PyNames { .put("__round__", new BuiltinDescription("(self, n=None)")) .build(); + public static ImmutableMap PY35_BUILTIN_METHODS = ImmutableMap.builder() + .putAll(PY3_BUILTIN_METHODS) + .put("__imatmul__", _self_other_descr) + .put("__matmul__", _self_other_descr) + .put("__rmatmul__", _self_other_descr) + .build(); + public static ImmutableMap getBuiltinMethods(LanguageLevel level) { - return level.isPy3K() ? PY3_BUILTIN_METHODS : PY2_BUILTIN_METHODS; + if (level.isAtLeast(LanguageLevel.PYTHON35)) { + return PY35_BUILTIN_METHODS; + } + else if (level.isAtLeast(LanguageLevel.PYTHON30)) { + return PY3_BUILTIN_METHODS; + } + else { + return PY2_BUILTIN_METHODS; + } } // canonical names, not forced by interpreter diff --git a/python/psi-api/src/com/jetbrains/python/PyTokenTypes.java b/python/psi-api/src/com/jetbrains/python/PyTokenTypes.java index 630668388aed..a54bdc39ad92 100644 --- a/python/psi-api/src/com/jetbrains/python/PyTokenTypes.java +++ b/python/psi-api/src/com/jetbrains/python/PyTokenTypes.java @@ -118,7 +118,7 @@ public class PyTokenTypes { public static final PyElementType RBRACKET = new PyElementType("RBRACKET");// ] public static final PyElementType LBRACE = new PyElementType("LBRACE");// { public static final PyElementType RBRACE = new PyElementType("RBRACE");// } - public static final PyElementType AT = new PyElementType("AT");// @ + public static final PyElementType AT = new PyElementType("AT", "__matmul__");// @ public static final PyElementType COMMA = new PyElementType("COMMA");// , public static final PyElementType COLON = new PyElementType("COLON");// : public static final PyElementType DOT = new PyElementType("DOT");// . @@ -128,6 +128,7 @@ public class PyTokenTypes { public static final PyElementType PLUSEQ = new PyElementType("PLUSEQ");// += public static final PyElementType MINUSEQ = new PyElementType("MINUSEQ");// -= public static final PyElementType MULTEQ = new PyElementType("MULTEQ");// *= + public static final PyElementType ATEQ = new PyElementType("ATEQ"); // @= public static final PyElementType DIVEQ = new PyElementType("DIVEQ"); // /= public static final PyElementType FLOORDIVEQ = new PyElementType("FLOORDIVEQ"); // //= public static final PyElementType PERCEQ = new PyElementType("PERCEQ");// %= @@ -139,10 +140,10 @@ public class PyTokenTypes { public static final PyElementType EXPEQ = new PyElementType("EXPEQ");// **= public static final TokenSet OPERATIONS = TokenSet.create( - PLUS, MINUS, MULT, EXP, DIV, FLOORDIV, PERC, LTLT, GTGT, AND, OR, + PLUS, MINUS, MULT, AT, EXP, DIV, FLOORDIV, PERC, LTLT, GTGT, AND, OR, XOR, TILDE, LT, GT, LE, GE, EQEQ, NE, NE_OLD, AT, COLON, TICK, EQ, PLUSEQ, MINUSEQ, - MULTEQ, DIVEQ, FLOORDIVEQ, PERCEQ, ANDEQ, OREQ, XOREQ, LTLTEQ, GTGTEQ, + MULTEQ, ATEQ, DIVEQ, FLOORDIVEQ, PERCEQ, ANDEQ, OREQ, XOREQ, LTLTEQ, GTGTEQ, EXPEQ); public static final TokenSet COMPARISON_OPERATIONS = TokenSet.create( @@ -150,8 +151,8 @@ public class PyTokenTypes { public static final TokenSet SHIFT_OPERATIONS = TokenSet.create(LTLT, GTGT); public static final TokenSet ADDITIVE_OPERATIONS = TokenSet.create(PLUS, MINUS); - public static final TokenSet MULTIPLICATIVE_OPERATIONS = TokenSet.create(MULT, FLOORDIV, DIV, PERC); - public static final TokenSet MULTIPLICATIVE_OR_EXP = TokenSet.create(MULT, FLOORDIV, DIV, PERC, EXP); + public static final TokenSet MULTIPLICATIVE_OPERATIONS = TokenSet.create(MULT, AT, FLOORDIV, DIV, PERC); + public static final TokenSet MULTIPLICATIVE_OR_EXP = TokenSet.create(MULT, AT, FLOORDIV, DIV, PERC, EXP); public static final TokenSet UNARY_OPERATIONS = TokenSet.create(PLUS, MINUS, TILDE); public static final TokenSet BITWISE_OPERATIONS = TokenSet.create(AND, OR, XOR); public static final TokenSet EQUALITY_OPERATIONS = TokenSet.create(EQEQ, NE, NE_OLD); @@ -162,7 +163,7 @@ public class PyTokenTypes { public static final TokenSet OPEN_BRACES = TokenSet.create(LBRACKET, LBRACE, LPAR); public static final TokenSet CLOSE_BRACES = TokenSet.create(RBRACKET, RBRACE, RPAR); - public static final TokenSet AUG_ASSIGN_OPERATIONS = TokenSet.create(PLUSEQ, MINUSEQ, MULTEQ, DIVEQ, + public static final TokenSet AUG_ASSIGN_OPERATIONS = TokenSet.create(PLUSEQ, MINUSEQ, MULTEQ, ATEQ, DIVEQ, PERCEQ, EXPEQ, GTGTEQ, LTLTEQ, ANDEQ, OREQ, XOREQ, FLOORDIVEQ); public static final PyElementType BACKSLASH = new PyElementType("BACKSLASH"); diff --git a/python/psi-api/src/com/jetbrains/python/psi/LanguageLevel.java b/python/psi-api/src/com/jetbrains/python/psi/LanguageLevel.java index a93f5ffb8767..1c56c2b60f3d 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/LanguageLevel.java +++ b/python/psi-api/src/com/jetbrains/python/psi/LanguageLevel.java @@ -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 */ @@ -32,10 +35,24 @@ public enum LanguageLevel { PYTHON31(31, true, false, true, true), PYTHON32(32, true, false, true, true), PYTHON33(33, true, false, true, true), - PYTHON34(34, true, false, true, true); + PYTHON34(34, true, false, true, true), + PYTHON35(35, true, false, true, true); + + public static List ALL_LEVELS = ImmutableList.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 = PYTHON33; + private static LanguageLevel DEFAULT3 = PYTHON34; public static LanguageLevel FORCE_LANGUAGE_LEVEL = null; @@ -121,6 +138,9 @@ public enum LanguageLevel { if (pythonVersion.startsWith("3.4")) { return PYTHON34; } + if (pythonVersion.startsWith("3.5")) { + return PYTHON35; + } return DEFAULT3; } return getDefault(); diff --git a/python/psi-api/src/com/jetbrains/python/psi/PyAugAssignmentStatement.java b/python/psi-api/src/com/jetbrains/python/psi/PyAugAssignmentStatement.java index 17ea926fb536..46d483ca7104 100644 --- a/python/psi-api/src/com/jetbrains/python/psi/PyAugAssignmentStatement.java +++ b/python/psi-api/src/com/jetbrains/python/psi/PyAugAssignmentStatement.java @@ -15,6 +15,7 @@ */ package com.jetbrains.python.psi; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -26,4 +27,6 @@ public interface PyAugAssignmentStatement extends PyStatement { PyExpression getTarget(); @Nullable PyExpression getValue(); + @Nullable + PsiElement getOperation(); } diff --git a/python/src/com/jetbrains/numpy/codeInsight/NumpyDocStringTypeProvider.java b/python/src/com/jetbrains/numpy/codeInsight/NumpyDocStringTypeProvider.java index 2d6dcb6a7379..bcd87f4fcb16 100644 --- a/python/src/com/jetbrains/numpy/codeInsight/NumpyDocStringTypeProvider.java +++ b/python/src/com/jetbrains/numpy/codeInsight/NumpyDocStringTypeProvider.java @@ -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); diff --git a/python/src/com/jetbrains/python/PyElementTypes.java b/python/src/com/jetbrains/python/PyElementTypes.java index 7a713524f6c4..400e21b178c7 100644 --- a/python/src/com/jetbrains/python/PyElementTypes.java +++ b/python/src/com/jetbrains/python/PyElementTypes.java @@ -127,7 +127,8 @@ public interface PyElementTypes { PyTokenTypes.OR, PyTokenTypes.XOR, PyTokenTypes.AND, PyTokenTypes.LTLT, PyTokenTypes.GTGT, PyTokenTypes.EQEQ, PyTokenTypes.GE, PyTokenTypes.LE, PyTokenTypes.NE, PyTokenTypes.NE_OLD, PyTokenTypes.IN_KEYWORD, PyTokenTypes.IS_KEYWORD, PyTokenTypes.NOT_KEYWORD, PyTokenTypes.PLUS, - PyTokenTypes.MINUS, PyTokenTypes.MULT, PyTokenTypes.FLOORDIV, PyTokenTypes.DIV, PyTokenTypes.PERC, PyTokenTypes.EXP); + PyTokenTypes.MINUS, PyTokenTypes.MULT, PyTokenTypes.AT, PyTokenTypes.FLOORDIV, PyTokenTypes.DIV, + PyTokenTypes.PERC, PyTokenTypes.EXP); TokenSet UNARY_OPS = TokenSet.create(PyTokenTypes.NOT_KEYWORD, PyTokenTypes.PLUS, PyTokenTypes.MINUS, PyTokenTypes.TILDE); diff --git a/python/src/com/jetbrains/python/codeInsight/PyStdReferenceContributor.java b/python/src/com/jetbrains/python/codeInsight/PyStdReferenceContributor.java index 5b0221d0c6ff..b9ecf6247fca 100644 --- a/python/src/com/jetbrains/python/codeInsight/PyStdReferenceContributor.java +++ b/python/src/com/jetbrains/python/codeInsight/PyStdReferenceContributor.java @@ -15,13 +15,11 @@ */ package com.jetbrains.python.codeInsight; +import com.intellij.patterns.PatternCondition; import com.intellij.psi.*; import com.intellij.util.ProcessingContext; import com.jetbrains.python.PyNames; -import com.jetbrains.python.psi.PyAssignmentStatement; -import com.jetbrains.python.psi.PySequenceExpression; -import com.jetbrains.python.psi.PyStringLiteralExpression; -import com.jetbrains.python.psi.PyTargetExpression; +import com.jetbrains.python.psi.*; import org.jetbrains.annotations.NotNull; import static com.intellij.patterns.PlatformPatterns.psiElement; @@ -30,6 +28,18 @@ import static com.intellij.patterns.PlatformPatterns.psiElement; * @author yole */ public class PyStdReferenceContributor extends PsiReferenceContributor { + public static final PatternCondition IN_OPTIONAL_PARENTHESIS_INSIDE_ASSIGNMENT = + new PatternCondition("in optional parenthesis inside assignment") { + @Override + public boolean accepts(@NotNull PsiElement element, ProcessingContext context) { + PsiElement parent = element.getParent(); + while (parent instanceof PyParenthesizedExpression) { + parent = parent.getParent(); + } + return parent instanceof PyAssignmentStatement; + } + }; + @Override public void registerReferenceProviders(@NotNull PsiReferenceRegistrar registrar) { registerClassAttributeReference(registrar, PyNames.ALL, new PsiReferenceProvider() { @@ -54,9 +64,10 @@ public class PyStdReferenceContributor extends PsiReferenceContributor { private static void registerClassAttributeReference(PsiReferenceRegistrar registrar, final String name, final PsiReferenceProvider provider) { - registrar.registerReferenceProvider(psiElement(PyStringLiteralExpression.class).withParent( - psiElement(PySequenceExpression.class).withParent( - psiElement(PyAssignmentStatement.class).withFirstChild( - psiElement(PyTargetExpression.class).withName(name)))), provider); - } + registrar.registerReferenceProvider(psiElement(PyStringLiteralExpression.class) + .withParent(psiElement(PySequenceExpression.class) + .with(IN_OPTIONAL_PARENTHESIS_INSIDE_ASSIGNMENT) + .inside(true, psiElement(PyAssignmentStatement.class) + .withFirstChild(psiElement(PyTargetExpression.class).withName(name)))), provider); + } } diff --git a/python/src/com/jetbrains/python/debugger/PyDebugRunner.java b/python/src/com/jetbrains/python/debugger/PyDebugRunner.java index d0628db29c52..206916bdf36d 100644 --- a/python/src/com/jetbrains/python/debugger/PyDebugRunner.java +++ b/python/src/com/jetbrains/python/debugger/PyDebugRunner.java @@ -63,7 +63,7 @@ public class PyDebugRunner extends GenericProgramRunner { public static final String CLIENT_PARAM = "--client"; public static final String PORT_PARAM = "--port"; public static final String FILE_PARAM = "--file"; - public static final String PYCHARM_PROJECT_ROOTS = "PYCHARM_PROJECT_ROOTS"; + public static final String IDE_PROJECT_ROOTS = "IDE_PROJECT_ROOTS"; @SuppressWarnings("SpellCheckingInspection") public static final String GEVENT_SUPPORT = "GEVENT_SUPPORT"; @@ -249,6 +249,6 @@ public class PyDebugRunner extends GenericProgramRunner { roots.add(contentRoot.getPath()); } - commandLine.getEnvironment().put(PYCHARM_PROJECT_ROOTS, StringUtil.join(roots, File.pathSeparator)); + commandLine.getEnvironment().put(IDE_PROJECT_ROOTS, StringUtil.join(roots, File.pathSeparator)); } } diff --git a/python/src/com/jetbrains/python/debugger/PyExceptionBreakpointProperties.java b/python/src/com/jetbrains/python/debugger/PyExceptionBreakpointProperties.java index 811f91f1f727..099d6d0811a2 100644 --- a/python/src/com/jetbrains/python/debugger/PyExceptionBreakpointProperties.java +++ b/python/src/com/jetbrains/python/debugger/PyExceptionBreakpointProperties.java @@ -42,7 +42,7 @@ public class PyExceptionBreakpointProperties extends ExceptionBreakpointProperti public PyExceptionBreakpointProperties(@NotNull final String exception) { myException = exception; myNotifyOnTerminate = true; - myIgnoreLibraries = true; + myIgnoreLibraries = false; } @Override diff --git a/python/src/com/jetbrains/python/formatter/PythonFormattingModelBuilder.java b/python/src/com/jetbrains/python/formatter/PythonFormattingModelBuilder.java index c468290a8514..04d0c69547da 100644 --- a/python/src/com/jetbrains/python/formatter/PythonFormattingModelBuilder.java +++ b/python/src/com/jetbrains/python/formatter/PythonFormattingModelBuilder.java @@ -108,6 +108,7 @@ public class PythonFormattingModelBuilder implements FormattingModelBuilderEx, C .between(FROM_KEYWORD, DOT).spaces(1) .between(DOT, IMPORT_KEYWORD).spaces(1) .around(DOT).spaces(0) + .aroundInside(AT, DECORATOR_CALL).none() .before(SEMICOLON).spaceIf(commonSettings.SPACE_BEFORE_SEMICOLON) .withinPairInside(LPAR, RPAR, ARGUMENT_LIST).spaceIf(commonSettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES) .withinPairInside(LPAR, RPAR, PARAMETER_LIST).spaceIf(commonSettings.SPACE_WITHIN_METHOD_PARENTHESES) diff --git a/python/src/com/jetbrains/python/inspections/PyPackageRequirementsInspection.java b/python/src/com/jetbrains/python/inspections/PyPackageRequirementsInspection.java index 0db1a087aa29..a92537dc50b3 100644 --- a/python/src/com/jetbrains/python/inspections/PyPackageRequirementsInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyPackageRequirementsInspection.java @@ -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 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 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.emptyList()); + } + } + private static class UIListener implements PyPackageManagerUI.Listener { private final Module myModule; diff --git a/python/src/com/jetbrains/python/inspections/PyPep8NamingInspection.java b/python/src/com/jetbrains/python/inspections/PyPep8NamingInspection.java index 1da2c46403e0..8dd34f25f31d 100644 --- a/python/src/com/jetbrains/python/inspections/PyPep8NamingInspection.java +++ b/python/src/com/jetbrains/python/inspections/PyPep8NamingInspection.java @@ -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 quickFixes = Lists.newArrayList(new PyRenameElementQuickFix()); + final List 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"); } } } diff --git a/python/src/com/jetbrains/python/PyAddImportFix.java b/python/src/com/jetbrains/python/inspections/quickfix/PyAddImportFix.java similarity index 96% rename from python/src/com/jetbrains/python/PyAddImportFix.java rename to python/src/com/jetbrains/python/inspections/quickfix/PyAddImportFix.java index 78d53f2a2122..fe49874ea11a 100644 --- a/python/src/com/jetbrains/python/PyAddImportFix.java +++ b/python/src/com/jetbrains/python/inspections/quickfix/PyAddImportFix.java @@ -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; diff --git a/python/src/com/jetbrains/python/quickFixes/RemoveTrailingBlankLinesFix.java b/python/src/com/jetbrains/python/inspections/quickfix/RemoveTrailingBlankLinesFix.java similarity index 98% rename from python/src/com/jetbrains/python/quickFixes/RemoveTrailingBlankLinesFix.java rename to python/src/com/jetbrains/python/inspections/quickfix/RemoveTrailingBlankLinesFix.java index 03c44fdced0b..b9d3eb27b57e 100644 --- a/python/src/com/jetbrains/python/quickFixes/RemoveTrailingBlankLinesFix.java +++ b/python/src/com/jetbrains/python/inspections/quickfix/RemoveTrailingBlankLinesFix.java @@ -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; diff --git a/python/src/com/jetbrains/python/inspections/unresolvedReference/PyPackageAliasesProvider.java b/python/src/com/jetbrains/python/inspections/unresolvedReference/PyPackageAliasesProvider.java new file mode 100644 index 000000000000..01ca2ba89b19 --- /dev/null +++ b/python/src/com/jetbrains/python/inspections/unresolvedReference/PyPackageAliasesProvider.java @@ -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 commonAliases = new HashMap(); + + 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"); + } +} diff --git a/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java b/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java index 4c8391ef689d..edb3cfec69ac 100644 --- a/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java +++ b/python/src/com/jetbrains/python/inspections/unresolvedReference/PyUnresolvedReferencesInspection.java @@ -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 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 actions) { + private void addCreateClassFix(@NonNls String refText, PsiElement element, List actions) { if (refText.length() > 2 && Character.isUpperCase(refText.charAt(0)) && !refText.toUpperCase().equals(refText) && PsiTreeUtil.getParentOfType(element, PyImportStatementBase.class) == null) { PsiElement anchor = element; diff --git a/python/src/com/jetbrains/python/lexer/Python.flex b/python/src/com/jetbrains/python/lexer/Python.flex index 07a627d8e15f..8755304365ba 100644 --- a/python/src/com/jetbrains/python/lexer/Python.flex +++ b/python/src/com/jetbrains/python/lexer/Python.flex @@ -160,6 +160,7 @@ return PyTokenTypes.DOCSTRING; } "-=" { return PyTokenTypes.MINUSEQ; } "**=" { return PyTokenTypes.EXPEQ; } "*=" { return PyTokenTypes.MULTEQ; } +"@=" { return PyTokenTypes.ATEQ; } "//=" { return PyTokenTypes.FLOORDIVEQ; } "/=" { return PyTokenTypes.DIVEQ; } "%=" { return PyTokenTypes.PERCEQ; } diff --git a/python/src/com/jetbrains/python/psi/impl/PyDictLiteralExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyDictLiteralExpressionImpl.java index e6010154cf7c..2bc1d58fd931 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyDictLiteralExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyDictLiteralExpressionImpl.java @@ -25,7 +25,7 @@ import com.jetbrains.python.psi.types.PyType; import com.jetbrains.python.psi.types.TypeEvalContext; import org.jetbrains.annotations.NotNull; -public class PyDictLiteralExpressionImpl extends PyElementImpl implements PyDictLiteralExpression { +public class PyDictLiteralExpressionImpl extends PySequenceExpressionImpl implements PyDictLiteralExpression { private static final TokenSet KEY_VALUE_EXPRESSIONS = TokenSet.create(PyElementTypes.KEY_VALUE_EXPRESSION); public PyDictLiteralExpressionImpl(ASTNode astNode) { diff --git a/python/src/com/jetbrains/python/psi/impl/PyListLiteralExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyListLiteralExpressionImpl.java index a71519266e48..cee81b15f6ea 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyListLiteralExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyListLiteralExpressionImpl.java @@ -18,13 +18,15 @@ package com.jetbrains.python.psi.impl; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; import com.intellij.util.IncorrectOperationException; -import com.jetbrains.python.PythonDialectsTokenSetProvider; -import com.jetbrains.python.psi.*; +import com.jetbrains.python.psi.PyElementGenerator; +import com.jetbrains.python.psi.PyElementVisitor; +import com.jetbrains.python.psi.PyExpression; +import com.jetbrains.python.psi.PyListLiteralExpression; import com.jetbrains.python.psi.types.PyType; import com.jetbrains.python.psi.types.TypeEvalContext; import org.jetbrains.annotations.NotNull; -public class PyListLiteralExpressionImpl extends PyElementImpl implements PyListLiteralExpression { +public class PyListLiteralExpressionImpl extends PySequenceExpressionImpl implements PyListLiteralExpression { public PyListLiteralExpressionImpl(ASTNode astNode) { super(astNode); } @@ -34,11 +36,6 @@ public class PyListLiteralExpressionImpl extends PyElementImpl implements PyList pyVisitor.visitPyListLiteralExpression(this); } - @NotNull - public PyExpression[] getElements() { - return childrenToPsi(PythonDialectsTokenSetProvider.INSTANCE.getExpressionTokens(), PyExpression.EMPTY_ARRAY); - } - public PsiElement add(@NotNull PsiElement psiElement) throws IncorrectOperationException { checkPyExpression(psiElement); PyExpression element = (PyExpression)psiElement; @@ -64,27 +61,6 @@ public class PyListLiteralExpressionImpl extends PyElementImpl implements PyList return PyElementGenerator.getInstance(getProject()).insertItemIntoList(this, null, (PyExpression)psiElement); } - @Override - public void deleteChildInternal(@NotNull ASTNode child) { - if (child.getPsi() instanceof PyExpression) { - PyExpression expression = (PyExpression)child.getPsi(); - ASTNode node = getNode(); - ASTNode exprNode = expression.getNode(); - ASTNode next = PyPsiUtils.getNextComma(exprNode); - ASTNode prev = PyPsiUtils.getPrevComma(exprNode); - super.deleteChildInternal(child); - if (next != null) { - deleteChildInternal(next); - } - else if (prev != null) { - deleteChildInternal(prev); - } - } - else { - super.deleteChildInternal(child); - } - } - public PyType getType(@NotNull TypeEvalContext context, @NotNull TypeEvalContext.Key key) { return PyBuiltinCache.getInstance(this).createLiteralCollectionType(this, "list", context); } diff --git a/python/src/com/jetbrains/python/psi/impl/PySequenceExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PySequenceExpressionImpl.java new file mode 100644 index 000000000000..e3b114d187c1 --- /dev/null +++ b/python/src/com/jetbrains/python/psi/impl/PySequenceExpressionImpl.java @@ -0,0 +1,40 @@ +package com.jetbrains.python.psi.impl; + +import com.intellij.lang.ASTNode; +import com.jetbrains.python.PythonDialectsTokenSetProvider; +import com.jetbrains.python.psi.PyExpression; +import org.jetbrains.annotations.NotNull; + +/** + * @author Mikhail Golubev + */ +public class PySequenceExpressionImpl extends PyElementImpl { + public PySequenceExpressionImpl(ASTNode astNode) { + super(astNode); + } + + @Override + public void deleteChildInternal(@NotNull ASTNode child) { + if (child.getPsi() instanceof PyExpression) { + PyExpression expression = (PyExpression)child.getPsi(); + ASTNode exprNode = expression.getNode(); + ASTNode next = PyPsiUtils.getNextComma(exprNode); + ASTNode prev = PyPsiUtils.getPrevComma(exprNode); + super.deleteChildInternal(child); + if (next != null) { + deleteChildInternal(next); + } + else if (prev != null) { + deleteChildInternal(prev); + } + } + else { + super.deleteChildInternal(child); + } + } + + @NotNull + public PyExpression[] getElements() { + return childrenToPsi(PythonDialectsTokenSetProvider.INSTANCE.getExpressionTokens(), PyExpression.EMPTY_ARRAY); + } +} diff --git a/python/src/com/jetbrains/python/psi/impl/PySetLiteralExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PySetLiteralExpressionImpl.java index 89c87692748a..0de568a5e123 100644 --- a/python/src/com/jetbrains/python/psi/impl/PySetLiteralExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PySetLiteralExpressionImpl.java @@ -16,8 +16,8 @@ package com.jetbrains.python.psi.impl; import com.intellij.lang.ASTNode; -import com.intellij.psi.util.PsiTreeUtil; -import com.jetbrains.python.psi.*; +import com.jetbrains.python.psi.PyElementVisitor; +import com.jetbrains.python.psi.PySetLiteralExpression; import com.jetbrains.python.psi.types.PyType; import com.jetbrains.python.psi.types.TypeEvalContext; import org.jetbrains.annotations.NotNull; @@ -25,7 +25,7 @@ import org.jetbrains.annotations.NotNull; /** * @author yole */ -public class PySetLiteralExpressionImpl extends PyElementImpl implements PySetLiteralExpression { +public class PySetLiteralExpressionImpl extends PySequenceExpressionImpl implements PySetLiteralExpression { public PySetLiteralExpressionImpl(ASTNode astNode) { super(astNode); } @@ -38,10 +38,4 @@ public class PySetLiteralExpressionImpl extends PyElementImpl implements PySetLi protected void acceptPyVisitor(PyElementVisitor pyVisitor) { pyVisitor.visitPySetLiteralExpression(this); } - - @NotNull - public PyExpression[] getElements() { - final PyExpression[] elements = PsiTreeUtil.getChildrenOfType(this, PyExpression.class); - return elements != null ? elements : PyExpression.EMPTY_ARRAY; - } } diff --git a/python/src/com/jetbrains/python/psi/impl/PyTupleExpressionImpl.java b/python/src/com/jetbrains/python/psi/impl/PyTupleExpressionImpl.java index 8810a14ecb21..8931504be773 100644 --- a/python/src/com/jetbrains/python/psi/impl/PyTupleExpressionImpl.java +++ b/python/src/com/jetbrains/python/psi/impl/PyTupleExpressionImpl.java @@ -16,10 +16,7 @@ package com.jetbrains.python.psi.impl; import com.intellij.lang.ASTNode; -import com.jetbrains.python.PythonDialectsTokenSetProvider; -import com.jetbrains.python.psi.PyElementVisitor; -import com.jetbrains.python.psi.PyExpression; -import com.jetbrains.python.psi.PyTupleExpression; +import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.types.PyTupleType; import com.jetbrains.python.psi.types.PyType; import com.jetbrains.python.psi.types.TypeEvalContext; @@ -31,7 +28,7 @@ import java.util.Iterator; /** * @author yole */ -public class PyTupleExpressionImpl extends PyElementImpl implements PyTupleExpression { +public class PyTupleExpressionImpl extends PySequenceExpressionImpl implements PyTupleExpression { public PyTupleExpressionImpl(ASTNode astNode) { super(astNode); } @@ -41,11 +38,6 @@ public class PyTupleExpressionImpl extends PyElementImpl implements PyTupleExpre pyVisitor.visitPyTupleExpression(this); } - @NotNull - public PyExpression[] getElements() { - return childrenToPsi(PythonDialectsTokenSetProvider.INSTANCE.getExpressionTokens(), PyExpression.EMPTY_ARRAY); - } - public PyType getType(@NotNull TypeEvalContext context, @NotNull TypeEvalContext.Key key) { final PyExpression[] elements = getElements(); final PyType[] types = new PyType[elements.length]; @@ -56,6 +48,19 @@ public class PyTupleExpressionImpl extends PyElementImpl implements PyTupleExpre } public Iterator iterator() { - return Arrays.asList(getElements()).iterator(); + return Arrays.asList(getElements()).iterator(); + } + + @Override + public void deleteChildInternal(@NotNull ASTNode child) { + super.deleteChildInternal(child); + final PyExpression[] children = getElements(); + final PyElementGenerator generator = PyElementGenerator.getInstance(getProject()); + if (children.length == 1 && PyPsiUtils.getNextComma(children[0].getNode()) == null ) { + addAfter(generator.createComma().getPsi(), children[0]); + } + else if (children.length == 0 && !(getParent() instanceof PyParenthesizedExpression)) { + replace(generator.createExpressionFromText(LanguageLevel.forElement(this), "()")); + } } } diff --git a/python/src/com/jetbrains/python/refactoring/PyReplaceExpressionUtil.java b/python/src/com/jetbrains/python/refactoring/PyReplaceExpressionUtil.java index 9b4c95f7d2b2..8aeba796877a 100644 --- a/python/src/com/jetbrains/python/refactoring/PyReplaceExpressionUtil.java +++ b/python/src/com/jetbrains/python/refactoring/PyReplaceExpressionUtil.java @@ -453,7 +453,7 @@ public class PyReplaceExpressionUtil implements PyElementTypes { else if (expr instanceof PyBinaryExpression) { final IElementType opType = getOperationType(expr); if (opType == EXP) priority = 3; - if (opType == MULT || opType == DIV || opType == PERC || opType == FLOORDIV) priority = 4; + if (opType == MULT || opType == AT || opType == DIV || opType == PERC || opType == FLOORDIV) priority = 4; if (opType == PLUS || opType == MINUS) priority = 5; if (opType == LTLT || opType == GTGT) priority = 6; if (opType == AND) priority = 7; diff --git a/python/src/com/jetbrains/python/refactoring/inline/PyInlineLocalHandler.java b/python/src/com/jetbrains/python/refactoring/inline/PyInlineLocalHandler.java index 82f42fdf9afa..910f35c3c570 100644 --- a/python/src/com/jetbrains/python/refactoring/inline/PyInlineLocalHandler.java +++ b/python/src/com/jetbrains/python/refactoring/inline/PyInlineLocalHandler.java @@ -50,7 +50,6 @@ import com.jetbrains.python.PythonLanguage; import com.jetbrains.python.codeInsight.controlflow.ReadWriteInstruction; import com.jetbrains.python.codeInsight.controlflow.ScopeOwner; import com.jetbrains.python.psi.*; -import com.jetbrains.python.psi.impl.PyAugAssignmentStatementImpl; import com.jetbrains.python.psi.impl.PyPsiUtils; import com.jetbrains.python.refactoring.PyDefUseUtil; import com.jetbrains.python.refactoring.PyReplaceExpressionUtil; @@ -315,8 +314,8 @@ public class PyInlineLocalHandler extends InlineActionHandler { private static PyExpression prepareValue(@NotNull PyStatement def, @NotNull String localName, @NotNull Project project) { final PyExpression value = getValue(def); assert value != null; - if (def instanceof PyAugAssignmentStatementImpl) { - final PyAugAssignmentStatementImpl expression = (PyAugAssignmentStatementImpl)def; + if (def instanceof PyAugAssignmentStatement) { + final PyAugAssignmentStatement expression = (PyAugAssignmentStatement)def; final PsiElement operation = expression.getOperation(); assert operation != null; final String op = operation.getText().replace('=', ' '); diff --git a/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersDelegate.java b/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersDelegate.java index c1c84717490a..c9d6ce6db003 100644 --- a/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersDelegate.java +++ b/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersDelegate.java @@ -36,7 +36,6 @@ import com.intellij.util.containers.ContainerUtil; import com.jetbrains.python.PyBundle; import com.jetbrains.python.psi.PyElement; import com.jetbrains.python.psi.PyFile; -import com.jetbrains.python.psi.PyUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -116,8 +115,8 @@ public class PyMoveModuleMembersDelegate extends MoveHandlerDelegate { // Fallback to the old way to select single element to move final PsiNamedElement e = PyMoveModuleMembersHelper.extractNamedElement(element); - if (e != null && PyMoveModuleMembersHelper.isMovableElement(e)) { - if (PyUtil.isTopLevel(e)) { + if (e != null && PyMoveModuleMembersHelper.hasMovableElementType(e)) { + if (PyMoveModuleMembersHelper.isMovableModuleMember(e)) { doMove(project, new PsiElement[]{e}, targetContainer, null); } else { diff --git a/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersDialog.java b/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersDialog.java index 207c115e3ea8..58f3f77f2607 100644 --- a/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersDialog.java +++ b/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersDialog.java @@ -5,6 +5,7 @@ import com.intellij.openapi.fileChooser.FileChooserDescriptor; import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory; import com.intellij.openapi.project.Project; import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.ui.DialogWrapperPeer; import com.intellij.openapi.ui.TextComponentAccessor; import com.intellij.openapi.ui.TextFieldWithBrowseButton; import com.intellij.openapi.util.io.FileUtil; @@ -17,10 +18,11 @@ import com.intellij.refactoring.ui.AbstractMemberSelectionTable; import com.intellij.refactoring.ui.RefactoringDialog; import com.intellij.ui.HideableDecorator; import com.intellij.ui.RowIcon; -import com.intellij.ui.ScrollPaneFactory; import com.intellij.ui.components.JBLabel; +import com.intellij.ui.components.JBScrollPane; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.ui.update.UiNotifyConnector; import com.jetbrains.python.PyBundle; import com.jetbrains.python.psi.PyClass; import com.jetbrains.python.psi.PyElement; @@ -35,6 +37,8 @@ import org.jetbrains.annotations.TestOnly; import javax.swing.*; import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; +import java.awt.*; +import java.io.File; import java.util.Collection; import java.util.Comparator; import java.util.List; @@ -52,6 +56,7 @@ public class PyMoveModuleMembersDialog extends RefactoringDialog { private final TopLevelSymbolsSelectionTable myMemberSelectionTable; private final PyModuleMemberInfoModel myModuleMemberModel; + private final boolean mySeveralElementsSelected; private JPanel myCenterPanel; private JPanel myTablePanel; private TextFieldWithBrowseButton myBrowseFieldWithButton; @@ -88,7 +93,7 @@ public class PyMoveModuleMembersDialog extends RefactoringDialog { * @param elements elements to move * @param destination destination where elements have to be moved */ - protected PyMoveModuleMembersDialog(@NotNull Project project, @NotNull List elements, @Nullable String destination) { + protected PyMoveModuleMembersDialog(@NotNull Project project, @NotNull final List elements, @Nullable String destination) { super(project, true); assert !elements.isEmpty(); @@ -115,6 +120,7 @@ public class PyMoveModuleMembersDialog extends RefactoringDialog { final List symbolsInfos = collectModuleMemberInfos(myModuleMemberModel.myPyFile); for (PyModuleMemberInfo info : symbolsInfos) { + //noinspection SuspiciousMethodCalls info.setChecked(elements.contains(info.getMember())); } myModuleMemberModel.memberInfoChanged(new MemberInfoChange(symbolsInfos)); @@ -126,8 +132,8 @@ public class PyMoveModuleMembersDialog extends RefactoringDialog { validateButtons(); } }); - // MoveMemberDialog for Java uses SeparatorFactory.createSeparator instead of custom border - final boolean tableIsVisible = PropertiesComponent.getInstance().getBoolean(BULK_MOVE_TABLE_VISIBLE, false); + mySeveralElementsSelected = elements.size() > 1; + final boolean tableIsVisible = mySeveralElementsSelected || PropertiesComponent.getInstance().getBoolean(BULK_MOVE_TABLE_VISIBLE, false); final String description; if (!tableIsVisible && elements.size() == 1) { if (firstElement instanceof PyFunction) { @@ -159,11 +165,45 @@ public class PyMoveModuleMembersDialog extends RefactoringDialog { } }; decorator.setOn(tableIsVisible); - decorator.setContentComponent(ScrollPaneFactory.createScrollPane(myMemberSelectionTable)); - validateButtons(); + decorator.setContentComponent(new JBScrollPane(myMemberSelectionTable) { + @Override + public Dimension getMinimumSize() { + // Prevent growth of the dialog after several expand/collapse actions + return new Dimension((int)super.getMinimumSize().getWidth(), 0); + } + }); + + UiNotifyConnector.doWhenFirstShown(myCenterPanel, new Runnable() { + @Override + public void run() { + enlargeDialogHeightIfNecessary(); + preselectLastPathComponent(myBrowseFieldWithButton.getTextField()); + } + }); init(); } + private void enlargeDialogHeightIfNecessary() { + if (mySeveralElementsSelected && !PropertiesComponent.getInstance(getProject()).getBoolean(BULK_MOVE_TABLE_VISIBLE, false)) { + final DialogWrapperPeer peer = getPeer(); + final Dimension realSize = peer.getSize(); + final double preferredHeight = peer.getPreferredSize().getHeight(); + if (realSize.getHeight() < preferredHeight) { + peer.setSize((int)realSize.getWidth(), (int)preferredHeight); + } + } + } + + private static void preselectLastPathComponent(@NotNull JTextField field) { + final String text = field.getText(); + final int start = text.lastIndexOf(File.separatorChar); + final int lastDotIndex = text.lastIndexOf('.'); + final int end = lastDotIndex < 0 ? text.length() : lastDotIndex; + if (start + 1 < end) { + field.select(start + 1, end); + } + } + @Nullable @Override protected String getDimensionServiceKey() { diff --git a/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersHelper.java b/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersHelper.java index f13b59bf5f92..dd631eb0719e 100644 --- a/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersHelper.java +++ b/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersHelper.java @@ -2,6 +2,7 @@ package com.jetbrains.python.refactoring.move; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiNamedElement; +import com.jetbrains.python.PyNames; import com.jetbrains.python.psi.*; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -27,11 +28,17 @@ public class PyMoveModuleMembersHelper { * @return whether this element is acceptable for "Move ..." refactoring */ public static boolean isMovableModuleMember(@NotNull PsiElement element) { - return isMovableElement(element) && PyUtil.isTopLevel(element); + if (!(hasMovableElementType(element) && PyUtil.isTopLevel(element))) { + return false; + } + if (element instanceof PyTargetExpression) { + return !(PyNames.ALL.equals(((PyTargetExpression)element).getName())) && isTargetOfSimpleAssignment(element); + } + return true; } - public static boolean isMovableElement(@NotNull PsiElement element) { - return element instanceof PyClass || element instanceof PyFunction || isTargetOfSimpleAssignment(element); + public static boolean hasMovableElementType(@NotNull PsiElement element) { + return element instanceof PyClass || element instanceof PyFunction || element instanceof PyTargetExpression; } /** @@ -60,7 +67,7 @@ public class PyMoveModuleMembersHelper { public static List getTopLevelModuleMembers(@NotNull PyFile pyFile) { final List result = new ArrayList(); for (PyTargetExpression attr : pyFile.getTopLevelAttributes()) { - if (isTargetOfSimpleAssignment(attr)) { + if (isMovableModuleMember(attr)) { result.add(attr); } } diff --git a/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersProcessor.java b/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersProcessor.java index c444f9d66f68..eb020bb9d902 100644 --- a/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersProcessor.java +++ b/python/src/com/jetbrains/python/refactoring/move/PyMoveModuleMembersProcessor.java @@ -35,6 +35,7 @@ import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import com.jetbrains.python.PyBundle; import com.jetbrains.python.PyNames; +import com.jetbrains.python.codeInsight.PyDunderAllReference; import com.jetbrains.python.codeInsight.dataflow.scope.ScopeUtil; import com.jetbrains.python.psi.*; import com.jetbrains.python.psi.resolve.QualifiedNameFinder; @@ -220,8 +221,13 @@ public class PyMoveModuleMembersProcessor extends BaseRefactoringProcessor { } if (usage instanceof PyStringLiteralExpression) { for (PsiReference ref : usage.getReferences()) { - if (ref.isReferenceTo(oldElement)) { - ref.bindToElement(newElement); + if ((ref instanceof PyDunderAllReference)) { + usage.delete(); + } + else { + if (ref.isReferenceTo(oldElement)) { + ref.bindToElement(newElement); + } } } } diff --git a/python/src/com/jetbrains/python/spellchecker/python.dic b/python/src/com/jetbrains/python/spellchecker/python.dic index d486a4f1ba34..d5d09e51ebdb 100644 --- a/python/src/com/jetbrains/python/spellchecker/python.dic +++ b/python/src/com/jetbrains/python/spellchecker/python.dic @@ -919,6 +919,7 @@ ihave ilog imagetext imagnumber +imatmul imode impls importfile @@ -1242,6 +1243,7 @@ mapdict mapstar markedsectionclose markobject +matmul maxamount maxbinsize maxcache @@ -1702,6 +1704,7 @@ ripemd rlecoderengine rledecoderengine rlshift +rmatmul rmcolorizer rmenu rmod diff --git a/python/src/com/jetbrains/python/validation/CompatibilityVisitor.java b/python/src/com/jetbrains/python/validation/CompatibilityVisitor.java index 67a7306a61b2..fb6d344475c7 100644 --- a/python/src/com/jetbrains/python/validation/CompatibilityVisitor.java +++ b/python/src/com/jetbrains/python/validation/CompatibilityVisitor.java @@ -22,6 +22,7 @@ import com.intellij.lang.ASTNode; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiWhiteSpace; +import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.QualifiedName; import com.jetbrains.python.PyNames; @@ -50,10 +51,10 @@ public abstract class CompatibilityVisitor extends PyAnnotator { AVAILABLE_PREFIXES.put(LanguageLevel.PYTHON30, Sets.newHashSet("R", "B")); AVAILABLE_PREFIXES.put(LanguageLevel.PYTHON31, Sets.newHashSet("R", "B", "BR")); AVAILABLE_PREFIXES.put(LanguageLevel.PYTHON32, Sets.newHashSet("R", "B", "BR")); - AVAILABLE_PREFIXES.put(LanguageLevel.PYTHON33, Sets.newHashSet("R", "U", "B", "BR", "RB")); - AVAILABLE_PREFIXES.put(LanguageLevel.PYTHON34, Sets.newHashSet("R", "U", "B", "BR", "RB")); } + private static final Set DEFAULT_PREFIXES = Sets.newHashSet(Sets.newHashSet("R", "U", "B", "BR", "RB")); + public CompatibilityVisitor(List versionsToProcess) { myVersionsToProcess = versionsToProcess; } @@ -195,6 +196,22 @@ public abstract class CompatibilityVisitor extends PyAnnotator { } commonRegisterProblem(message, " not support <>, use != instead.", len, node, new ReplaceNotEqOperatorQuickFix()); } + else if (node.isOperator("@")) { + checkMatrixMultiplicationOperator(node.getPsiOperator()); + } + } + + private void checkMatrixMultiplicationOperator(PsiElement node) { + boolean problem = false; + for (LanguageLevel level : myVersionsToProcess) { + if (level.isOlderThan(LanguageLevel.PYTHON35)) { + problem = true; + break; + } + } + if (problem) { + registerProblem(node, "Python versions < 3.5 do not support matrix multiplication operators"); + } } @Override @@ -254,7 +271,8 @@ public abstract class CompatibilityVisitor extends PyAnnotator { final LanguageLevel languageLevel = myVersionsToProcess.get(i); if (prefix.isEmpty()) continue; - final Set prefixes = AVAILABLE_PREFIXES.get(languageLevel); + final Set prefixesForLanguageLevel = AVAILABLE_PREFIXES.get(languageLevel); + final Set prefixes = prefixesForLanguageLevel != null ? prefixesForLanguageLevel : DEFAULT_PREFIXES; if (!prefixes.contains(prefix)) len = appendLanguageLevel(message, len, languageLevel); } @@ -541,6 +559,18 @@ public abstract class CompatibilityVisitor extends PyAnnotator { } } + @Override + public void visitPyAugAssignmentStatement(PyAugAssignmentStatement node) { + super.visitPyAugAssignmentStatement(node); + final PsiElement operation = node.getOperation(); + if (operation != null) { + final IElementType operationType = operation.getNode().getElementType(); + if (PyTokenTypes.ATEQ.equals(operationType)) { + checkMatrixMultiplicationOperator(operation); + } + } + } + private static class YieldVisitor extends PyElementVisitor { private boolean _haveYield = false; diff --git a/python/src/com/jetbrains/python/validation/Pep8ExternalAnnotator.java b/python/src/com/jetbrains/python/validation/Pep8ExternalAnnotator.java index 7b2d3233b369..f8642b600202 100644 --- a/python/src/com/jetbrains/python/validation/Pep8ExternalAnnotator.java +++ b/python/src/com/jetbrains/python/validation/Pep8ExternalAnnotator.java @@ -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; diff --git a/python/src/com/jetbrains/python/validation/UnsupportedFeaturesUtil.java b/python/src/com/jetbrains/python/validation/UnsupportedFeaturesUtil.java index 4018b339fc5d..a84651c009ab 100644 --- a/python/src/com/jetbrains/python/validation/UnsupportedFeaturesUtil.java +++ b/python/src/com/jetbrains/python/validation/UnsupportedFeaturesUtil.java @@ -41,8 +41,8 @@ public class UnsupportedFeaturesUtil { public static Map> BUILTINS = new HashMap>(); public static Map> MODULES = new HashMap>(); public static Map>> CLASS_METHODS = new HashMap>>(); + public static final List ALL_LANGUAGE_LEVELS = new ArrayList(); - public static Vector ALL_LANGUAGE_LEVELS; static { try { fillMaps(); @@ -52,7 +52,9 @@ public class UnsupportedFeaturesUtil { Logger log = Logger.getInstance(UnsupportedFeaturesUtil.class.getName()); log.error("Cannot find \"versions.xml\". " + e.getMessage()); } - fillAllLanguageLeves(); + for (LanguageLevel level : LanguageLevel.ALL_LEVELS) { + ALL_LANGUAGE_LEVELS.add(level.toString()); + } } private static void fillTestCaseMethods() throws IOException { @@ -72,19 +74,6 @@ public class UnsupportedFeaturesUtil { } } - private static void fillAllLanguageLeves() { - ALL_LANGUAGE_LEVELS = new Vector(); - ALL_LANGUAGE_LEVELS.add(LanguageLevel.PYTHON24.toString()); - ALL_LANGUAGE_LEVELS.add(LanguageLevel.PYTHON25.toString()); - ALL_LANGUAGE_LEVELS.add(LanguageLevel.PYTHON26.toString()); - ALL_LANGUAGE_LEVELS.add(LanguageLevel.PYTHON27.toString()); - ALL_LANGUAGE_LEVELS.add(LanguageLevel.PYTHON30.toString()); - ALL_LANGUAGE_LEVELS.add(LanguageLevel.PYTHON31.toString()); - ALL_LANGUAGE_LEVELS.add(LanguageLevel.PYTHON32.toString()); - ALL_LANGUAGE_LEVELS.add(LanguageLevel.PYTHON33.toString()); - ALL_LANGUAGE_LEVELS.add(LanguageLevel.PYTHON34.toString()); - } - private static void fillMaps() throws IOException { Logger log = Logger.getInstance(UnsupportedFeaturesUtil.class.getName()); FileReader reader = new FileReader(PythonHelpersLocator.getHelperPath("/tools/versions.xml")); diff --git a/python/testData/completion/matMul.after.py b/python/testData/completion/matMul.after.py new file mode 100644 index 000000000000..8d677c50431a --- /dev/null +++ b/python/testData/completion/matMul.after.py @@ -0,0 +1,2 @@ +class C: + def __matmul__(self, other): diff --git a/python/testData/completion/matMul.py b/python/testData/completion/matMul.py new file mode 100644 index 000000000000..e18502dd6752 --- /dev/null +++ b/python/testData/completion/matMul.py @@ -0,0 +1,2 @@ +class C: + def __matmul diff --git a/python/testData/inspections/PyCompatibilityInspection/matMul.py b/python/testData/inspections/PyCompatibilityInspection/matMul.py new file mode 100644 index 000000000000..d67dcc2221f8 --- /dev/null +++ b/python/testData/inspections/PyCompatibilityInspection/matMul.py @@ -0,0 +1,2 @@ +x @ y +x @= y diff --git a/python/testData/inspections/PyNumpyType/Dtype.py b/python/testData/inspections/PyNumpyType/Dtype.py new file mode 100644 index 000000000000..3da74820d977 --- /dev/null +++ b/python/testData/inspections/PyNumpyType/Dtype.py @@ -0,0 +1,43 @@ +def maximum_fill_value(obj): + """ + Return the minimum value that can be represented by the dtype of an object. + + This function is useful for calculating a fill value suitable for + taking the maximum of an array with a given dtype. + + Parameters + ---------- + obj : dtype + An object that can be queried for it's numeric type. + + Returns + ------- + val : scalar + The minimum representable value. + + Raises + ------ + TypeError + If `obj` isn't a suitable numeric type. + + """ + errmsg = "Unsuitable type for calculating maximum." + if hasattr(obj, 'dtype'): + return _recursive_extremum_fill_value(obj.dtype, max_filler) + elif isinstance(obj, float): + return max_filler[ntypes.typeDict['float_']] + elif isinstance(obj, int): + return max_filler[ntypes.typeDict['int_']] + elif isinstance(obj, long): + return max_filler[ntypes.typeDict['uint']] + elif isinstance(obj, np.dtype): + return max_filler[obj] + else: + raise TypeError(errmsg) + +a = np.int8() +maximum_fill_value(a) + + +maximum_fill_value(('i4',[('r','u1'), ('g','u1'), ('b','u1'), ('a','u1')])) +maximum_fill_value("i8,f8,S5") diff --git a/python/testData/inspections/PyNumpyType/NominalType.py b/python/testData/inspections/PyNumpyType/NominalType.py new file mode 100644 index 000000000000..9ca4081f4a01 --- /dev/null +++ b/python/testData/inspections/PyNumpyType/NominalType.py @@ -0,0 +1,90 @@ + +def cond(x, p=None): + """ + Compute the condition number of a matrix. + + This function is capable of returning the condition number using + one of seven different norms, depending on the value of `p` (see + Parameters below). + + Parameters + ---------- + x : (M, N) array_like + The matrix whose condition number is sought. + p : {None, 1, -1, 2, -2, inf, -inf, 'fro'}, optional + Order of the norm: + + ===== ============================ + p norm for matrices + ===== ============================ + None 2-norm, computed directly using the ``SVD`` + 'fro' Frobenius norm + inf max(sum(abs(x), axis=1)) + -inf min(sum(abs(x), axis=1)) + 1 max(sum(abs(x), axis=0)) + -1 min(sum(abs(x), axis=0)) + 2 2-norm (largest sing. value) + -2 smallest singular value + ===== ============================ + + inf means the numpy.inf object, and the Frobenius norm is + the root-of-sum-of-squares norm. + + Returns + ------- + c : {float, inf} + The condition number of the matrix. May be infinite. + + See Also + -------- + numpy.linalg.norm + + Notes + ----- + The condition number of `x` is defined as the norm of `x` times the + norm of the inverse of `x` [1]_; the norm can be the usual L2-norm + (root-of-sum-of-squares) or one of a number of other matrix norms. + + References + ---------- + .. [1] G. Strang, *Linear Algebra and Its Applications*, Orlando, FL, + Academic Press, Inc., 1980, pg. 285. + + Examples + -------- + >>> from numpy import linalg as LA + >>> a = np.array([[1, 0, -1], [0, 1, 0], [1, 0, 1]]) + >>> a + array([[ 1, 0, -1], + [ 0, 1, 0], + [ 1, 0, 1]]) + >>> LA.cond(a) + 1.4142135623730951 + >>> LA.cond(a, 'fro') + 3.1622776601683795 + >>> LA.cond(a, np.inf) + 2.0 + >>> LA.cond(a, -np.inf) + 1.0 + >>> LA.cond(a, 1) + 2.0 + >>> LA.cond(a, -1) + 1.0 + >>> LA.cond(a, 2) + 1.4142135623730951 + >>> LA.cond(a, -2) + 0.70710678118654746 + >>> min(LA.svd(a, compute_uv=0))*min(LA.svd(LA.inv(a), compute_uv=0)) + 0.70710678118654746 + + """ + x = asarray(x) # in case we have a matrix + if p is None: + s = svd(x, compute_uv=False) + return s[0]/s[-1] + else: + return norm(x, p)*norm(inv(x), p) + +a = np.array([[1, 0, -1], [0, 1, 0], [1, 0, 1]]) + +cond(a, "fro") \ No newline at end of file diff --git a/python/testData/psi/MatMul.py b/python/testData/psi/MatMul.py new file mode 100644 index 000000000000..4cd35008d8af --- /dev/null +++ b/python/testData/psi/MatMul.py @@ -0,0 +1,5 @@ +x @ y +x @ y @ z +x @ y * z +x + y @ z +z @= x diff --git a/python/testData/psi/MatMul.txt b/python/testData/psi/MatMul.txt new file mode 100644 index 000000000000..44ff4ee93774 --- /dev/null +++ b/python/testData/psi/MatMul.txt @@ -0,0 +1,67 @@ +PyFile:MatMul.py + PyExpressionStatement + PyBinaryExpression + PyReferenceExpression: x + PsiElement(Py:IDENTIFIER)('x') + PsiWhiteSpace(' ') + PsiElement(Py:AT)('@') + PsiWhiteSpace(' ') + PyReferenceExpression: y + PsiElement(Py:IDENTIFIER)('y') + PsiWhiteSpace('\n') + PyExpressionStatement + PyBinaryExpression + PyBinaryExpression + PyReferenceExpression: x + PsiElement(Py:IDENTIFIER)('x') + PsiWhiteSpace(' ') + PsiElement(Py:AT)('@') + PsiWhiteSpace(' ') + PyReferenceExpression: y + PsiElement(Py:IDENTIFIER)('y') + PsiWhiteSpace(' ') + PsiElement(Py:AT)('@') + PsiWhiteSpace(' ') + PyReferenceExpression: z + PsiElement(Py:IDENTIFIER)('z') + PsiWhiteSpace('\n') + PyExpressionStatement + PyBinaryExpression + PyBinaryExpression + PyReferenceExpression: x + PsiElement(Py:IDENTIFIER)('x') + PsiWhiteSpace(' ') + PsiElement(Py:AT)('@') + PsiWhiteSpace(' ') + PyReferenceExpression: y + PsiElement(Py:IDENTIFIER)('y') + PsiWhiteSpace(' ') + PsiElement(Py:MULT)('*') + PsiWhiteSpace(' ') + PyReferenceExpression: z + PsiElement(Py:IDENTIFIER)('z') + PsiWhiteSpace('\n') + PyExpressionStatement + PyBinaryExpression + PyReferenceExpression: x + PsiElement(Py:IDENTIFIER)('x') + PsiWhiteSpace(' ') + PsiElement(Py:PLUS)('+') + PsiWhiteSpace(' ') + PyBinaryExpression + PyReferenceExpression: y + PsiElement(Py:IDENTIFIER)('y') + PsiWhiteSpace(' ') + PsiElement(Py:AT)('@') + PsiWhiteSpace(' ') + PyReferenceExpression: z + PsiElement(Py:IDENTIFIER)('z') + PsiWhiteSpace('\n') + PyAugAssignmentStatement + PyReferenceExpression: z + PsiElement(Py:IDENTIFIER)('z') + PsiWhiteSpace(' ') + PsiElement(Py:ATEQ)('@=') + PsiWhiteSpace(' ') + PyReferenceExpression: x + PsiElement(Py:IDENTIFIER)('x') \ No newline at end of file diff --git a/python/testData/refactoring/inlinelocal/operatorPrecedence/matrixMultiplication.after.py b/python/testData/refactoring/inlinelocal/operatorPrecedence/matrixMultiplication.after.py new file mode 100644 index 000000000000..932b7d34be33 --- /dev/null +++ b/python/testData/refactoring/inlinelocal/operatorPrecedence/matrixMultiplication.after.py @@ -0,0 +1,57 @@ +(y @ z)[::-5] +(y @ z)[5] +(y @ z)(5) +(y @ z).foo + +-(y @ z) ++(y @ z) +~(y @ z) + +5 ** (y @ z) +(y @ z) ** 5 + +5 * y @ z +y @ z * 5 + +5 / (y @ z) +y @ z / 5 + +5 // (y @ z) +y @ z // 5 + +5 + y @ z +y @ z + 5 + +y @ z - 5 +5 - y @ z + +5 >> y @ z +y @ z << 5 + +5 & y @ z +y @ z & 5 + +5 ^ y @ z +y @ z ^ 5 + +5 | y @ z +y @ z | 5 + +() in y @ z +y @ z in () + +5 is y @ z +y @ z is 5 + +5 < y @ z +y @ z < 5 + +not y @ z + +5 and y @ z +y @ z and 5 + +5 or y @ z +y @ z or 5 + +y @ z if y @ z else y @ z diff --git a/python/testData/refactoring/move/dunderAll/after/src/a.py b/python/testData/refactoring/move/dunderAll/after/src/a.py new file mode 100644 index 000000000000..2baf29a799ba --- /dev/null +++ b/python/testData/refactoring/move/dunderAll/after/src/a.py @@ -0,0 +1,8 @@ +__all__ = ['C'] + + + + + +class C: + pass \ No newline at end of file diff --git a/python/testData/refactoring/move/dunderAll/after/src/b.py b/python/testData/refactoring/move/dunderAll/after/src/b.py new file mode 100644 index 000000000000..06075aebd98e --- /dev/null +++ b/python/testData/refactoring/move/dunderAll/after/src/b.py @@ -0,0 +1,2 @@ +def func(): + pass \ No newline at end of file diff --git a/python/testData/refactoring/move/dunderAll/before/src/a.py b/python/testData/refactoring/move/dunderAll/before/src/a.py new file mode 100644 index 000000000000..44885d7e59c3 --- /dev/null +++ b/python/testData/refactoring/move/dunderAll/before/src/a.py @@ -0,0 +1,9 @@ +__all__ = ['func', 'C'] + + +def func(): + pass + + +class C: + pass \ No newline at end of file diff --git a/python/testData/refactoring/move/dunderAll/before/src/b.py b/python/testData/refactoring/move/dunderAll/before/src/b.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/refactoring/move/dunderAllSingleElementTuple/after/src/a.py b/python/testData/refactoring/move/dunderAllSingleElementTuple/after/src/a.py new file mode 100644 index 000000000000..1fe7dabf9398 --- /dev/null +++ b/python/testData/refactoring/move/dunderAllSingleElementTuple/after/src/a.py @@ -0,0 +1,5 @@ +__all__ = () + + +class C: + pass \ No newline at end of file diff --git a/python/testData/refactoring/move/dunderAllSingleElementTuple/after/src/b.py b/python/testData/refactoring/move/dunderAllSingleElementTuple/after/src/b.py new file mode 100644 index 000000000000..06075aebd98e --- /dev/null +++ b/python/testData/refactoring/move/dunderAllSingleElementTuple/after/src/b.py @@ -0,0 +1,2 @@ +def func(): + pass \ No newline at end of file diff --git a/python/testData/refactoring/move/dunderAllSingleElementTuple/before/src/a.py b/python/testData/refactoring/move/dunderAllSingleElementTuple/before/src/a.py new file mode 100644 index 000000000000..5cbf71790ced --- /dev/null +++ b/python/testData/refactoring/move/dunderAllSingleElementTuple/before/src/a.py @@ -0,0 +1,9 @@ +__all__ = 'func', + + +def func(): + pass + + +class C: + pass \ No newline at end of file diff --git a/python/testData/refactoring/move/dunderAllSingleElementTuple/before/src/b.py b/python/testData/refactoring/move/dunderAllSingleElementTuple/before/src/b.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/refactoring/move/dunderAllTwoElementsTuple/after/src/a.py b/python/testData/refactoring/move/dunderAllTwoElementsTuple/after/src/a.py new file mode 100644 index 000000000000..94cfac702a68 --- /dev/null +++ b/python/testData/refactoring/move/dunderAllTwoElementsTuple/after/src/a.py @@ -0,0 +1,8 @@ +__all__ = ('C',) + + + + + +class C: + pass \ No newline at end of file diff --git a/python/testData/refactoring/move/dunderAllTwoElementsTuple/after/src/b.py b/python/testData/refactoring/move/dunderAllTwoElementsTuple/after/src/b.py new file mode 100644 index 000000000000..06075aebd98e --- /dev/null +++ b/python/testData/refactoring/move/dunderAllTwoElementsTuple/after/src/b.py @@ -0,0 +1,2 @@ +def func(): + pass \ No newline at end of file diff --git a/python/testData/refactoring/move/dunderAllTwoElementsTuple/before/src/a.py b/python/testData/refactoring/move/dunderAllTwoElementsTuple/before/src/a.py new file mode 100644 index 000000000000..d51579fb56a1 --- /dev/null +++ b/python/testData/refactoring/move/dunderAllTwoElementsTuple/before/src/a.py @@ -0,0 +1,9 @@ +__all__ = ('func', 'C') + + +def func(): + pass + + +class C: + pass \ No newline at end of file diff --git a/python/testData/refactoring/move/dunderAllTwoElementsTuple/before/src/b.py b/python/testData/refactoring/move/dunderAllTwoElementsTuple/before/src/b.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/testData/resolve/MatMul.py b/python/testData/resolve/MatMul.py new file mode 100644 index 000000000000..d3315dfe09b3 --- /dev/null +++ b/python/testData/resolve/MatMul.py @@ -0,0 +1,8 @@ +class C: + def __matmul__(self, other): + return self + + +x = C() +x @ y +# diff --git a/python/testData/resolve/RMatMul.py b/python/testData/resolve/RMatMul.py new file mode 100644 index 000000000000..ed242419d045 --- /dev/null +++ b/python/testData/resolve/RMatMul.py @@ -0,0 +1,8 @@ +class C: + def __rmatmul__(self, other): + return self + + +x = C() +y @ x +# diff --git a/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java b/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java index c80d7216a55a..ab4e64f4bad3 100644 --- a/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java +++ b/python/testSrc/com/jetbrains/env/python/PythonDebuggerTest.java @@ -428,7 +428,7 @@ public class PythonDebuggerTest extends PyEnvTestCase { addExceptionBreakpoint(fixture, properties); } - public void testExceptionBreakpointIgnoreLibraries() throws Exception { + public void testExceptionBreakpointIgnoreLibrariesOnRaise() throws Exception { runPythonTest(new PyDebuggerTask("/debug", "test_ignore_lib.py") { @Override public void before() throws Exception { @@ -450,6 +450,23 @@ public class PythonDebuggerTest extends PyEnvTestCase { }); } + public void testExceptionBreakpointIgnoreLibrariesOnTerminate() throws Exception { + runPythonTest(new PyDebuggerTask("/debug", "test_ignore_lib.py") { + @Override + public void before() throws Exception { + createExceptionBreak(myFixture, true, false, false, true); + } + + @Override + public void testing() throws Exception { + waitForPause(); + eval("stopped_in_user_file").hasValue("True"); + resume(); + waitForTerminate(); + } + }); + } + public void testMultithreading() throws Exception { runPythonTest(new PyDebuggerTask("/debug", "test_multithread.py") { @Override diff --git a/python/testSrc/com/jetbrains/python/Py3CompletionTest.java b/python/testSrc/com/jetbrains/python/Py3CompletionTest.java index 51b463948b03..ea154cb1084c 100644 --- a/python/testSrc/com/jetbrains/python/Py3CompletionTest.java +++ b/python/testSrc/com/jetbrains/python/Py3CompletionTest.java @@ -141,4 +141,14 @@ public class Py3CompletionTest extends PyTestCase { public void testNotImportedSubmodulesOfNamespacePackage() { doMultiFileTest(); } + + // PY-15390 + public void testMatMul() { + runWithLanguageLevel(LanguageLevel.PYTHON35, new Runnable() { + @Override + public void run() { + doTest(); + } + }); + } } diff --git a/python/testSrc/com/jetbrains/python/PyResolveTest.java b/python/testSrc/com/jetbrains/python/PyResolveTest.java index 78be57f40c5a..27c7558970b9 100644 --- a/python/testSrc/com/jetbrains/python/PyResolveTest.java +++ b/python/testSrc/com/jetbrains/python/PyResolveTest.java @@ -571,4 +571,14 @@ public class PyResolveTest extends PyResolveTestCase { public void testResolveAttributesUsingOldStyleMROWhenUnresolvedAncestorsAndC3Fails() { assertResolvesTo(PyFunction.class, "foo"); } + + // PY-15390 + public void testMatMul() { + assertResolvesTo(PyFunction.class, "__matmul__"); + } + + // PY-15390 + public void testRMatMul() { + assertResolvesTo(PyFunction.class, "__rmatmul__"); + } } diff --git a/python/testSrc/com/jetbrains/python/PythonParsingTest.java b/python/testSrc/com/jetbrains/python/PythonParsingTest.java index 9bdc65e52428..ecc415216428 100644 --- a/python/testSrc/com/jetbrains/python/PythonParsingTest.java +++ b/python/testSrc/com/jetbrains/python/PythonParsingTest.java @@ -468,6 +468,11 @@ public class PythonParsingTest extends ParsingTestCase { doTest(); } + // PY-15390 + public void testMatMul() { + doTest(LanguageLevel.PYTHON35); + } + public void doTest(LanguageLevel languageLevel) { LanguageLevel prev = myLanguageLevel; myLanguageLevel = languageLevel; diff --git a/python/testSrc/com/jetbrains/python/inspections/PyCompatibilityInspectionTest.java b/python/testSrc/com/jetbrains/python/inspections/PyCompatibilityInspectionTest.java index b46c523b0993..b941defb2b16 100644 --- a/python/testSrc/com/jetbrains/python/inspections/PyCompatibilityInspectionTest.java +++ b/python/testSrc/com/jetbrains/python/inspections/PyCompatibilityInspectionTest.java @@ -150,6 +150,11 @@ public class PyCompatibilityInspectionTest extends PyTestCase { doTest(); } + // PY-15390 + public void testMatMul() { + doTest(LanguageLevel.PYTHON35); + } + private void doTest(@NotNull LanguageLevel level) { runWithLanguageLevel(level, new Runnable() { @Override diff --git a/python/testSrc/com/jetbrains/python/inspections/PyNumpyTypeTest.java b/python/testSrc/com/jetbrains/python/inspections/PyNumpyTypeTest.java new file mode 100644 index 000000000000..26ad34baee3e --- /dev/null +++ b/python/testSrc/com/jetbrains/python/inspections/PyNumpyTypeTest.java @@ -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 com.jetbrains.python.inspections; + +import com.jetbrains.python.fixtures.PyTestCase; + +public class PyNumpyTypeTest extends PyTestCase { + public static final String TEST_DIRECTORY = "inspections/PyNumpyType/"; + + private void doTest() { + myFixture.configureByFile(TEST_DIRECTORY + getTestName(false) + ".py"); + myFixture.enableInspections(PyTypeCheckerInspection.class); + myFixture.checkHighlighting(true, false, true); + } + + public void testNominalType() { + doTest(); + } + + public void testDtype() { + doTest(); + } +} diff --git a/python/testSrc/com/jetbrains/python/refactoring/PyInlineLocalTest.java b/python/testSrc/com/jetbrains/python/refactoring/PyInlineLocalTest.java index 993c0fd794b2..30e68e38ece0 100644 --- a/python/testSrc/com/jetbrains/python/refactoring/PyInlineLocalTest.java +++ b/python/testSrc/com/jetbrains/python/refactoring/PyInlineLocalTest.java @@ -145,6 +145,11 @@ public class PyInlineLocalTest extends PyTestCase { checkOperatorPrecedence("x = 10 if True else 2", "conditional"); } + // PY-15390 + public void testMatMulPrecedence() throws Exception { + checkOperatorPrecedence("x = y @ z", "matrixMultiplication"); + } + private void checkOperatorPrecedence(@NotNull final String firstLine, @NotNull String resultPrefix) throws Exception { myFixture.configureByFile("/refactoring/inlinelocal/operatorPrecedence/template.py"); WriteCommandAction.runWriteCommandAction(myFixture.getProject(), new Runnable() { diff --git a/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java b/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java index cbb5c10669a4..37c3d40f2c07 100644 --- a/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java +++ b/python/testSrc/com/jetbrains/python/refactoring/PyMoveTest.java @@ -319,7 +319,22 @@ public class PyMoveTest extends PyTestCase { doMoveSymbolsTest("b.py", "f", "A"); } - private void doMoveFileTest(String fileName, String toDirName) { + // PY-15343 + public void testDunderAll() { + doMoveSymbolTest("func", "b.py"); + } + + // PY-15343 + public void testDunderAllSingleElementTuple() { + doMoveSymbolTest("func", "b.py"); + } + + // PY-15343 + public void testDunderAllTwoElementsTuple() { + doMoveSymbolTest("func", "b.py"); + } + + private void doMoveFileTest(String fileName, String toDirName) { Project project = myFixture.getProject(); PsiManager manager = PsiManager.getInstance(project); @@ -340,7 +355,7 @@ public class PyMoveTest extends PyTestCase { VirtualFile toVirtualDir = dir1.findFileByRelativePath(toDirName); assertNotNull(toVirtualDir); PsiDirectory toDir = manager.findDirectory(toVirtualDir); - new MoveFilesOrDirectoriesProcessor(project, new PsiElement[] {file}, toDir, false, false, null, null).run(); + new MoveFilesOrDirectoriesProcessor(project, new PsiElement[]{file}, toDir, false, false, null, null).run(); VirtualFile dir2 = getVirtualFileByName(PythonTestUtil.getTestDataPath() + rootAfter); try { diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml index 73f95eea746e..53da14d89b25 100644 --- a/resources/src/META-INF/IdeaPlugin.xml +++ b/resources/src/META-INF/IdeaPlugin.xml @@ -638,7 +638,7 @@ groupName="Declaration redundancy" enabledByDefault="false" level="WARNING" cleanupTool="true" implementationClass="com.intellij.codeInspection.unneededThrows.RedundantThrowsDeclaration" /> @@ -1266,6 +1447,7 @@ @@ -1348,6 +1537,7 @@ \ No newline at end of file