mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
Generated
-1
@@ -238,7 +238,6 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/tasks/tasks-java/tasks-java.iml" filepath="$PROJECT_DIR$/plugins/tasks/tasks-java/tasks-java.iml" group="plugins/tasks" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/tasks/tasks-tests/tasks-tests.iml" filepath="$PROJECT_DIR$/plugins/tasks/tasks-tests/tasks-tests.iml" group="plugins/tasks" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/terminal/terminal.iml" filepath="$PROJECT_DIR$/plugins/terminal/terminal.iml" group="plugins" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/testFramework/test-framework-java8.iml" filepath="$PROJECT_DIR$/platform/testFramework/test-framework-java8.iml" group="platform" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/testFramework/testFramework.iml" filepath="$PROJECT_DIR$/platform/testFramework/testFramework.iml" group="platform" />
|
||||
<module fileurl="file://$PROJECT_DIR$/java/testFramework/testFramework-java.iml" filepath="$PROJECT_DIR$/java/testFramework/testFramework-java.iml" group="java" />
|
||||
<module fileurl="file://$PROJECT_DIR$/platform/testRunner/testRunner.iml" filepath="$PROJECT_DIR$/platform/testRunner/testRunner.iml" group="platform" />
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
import groovy.transform.Immutable
|
||||
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
class ApplicationInfoProperties {
|
||||
final String majorVersion
|
||||
final String minorVersion
|
||||
final boolean isEAP
|
||||
final InstallOverProperties installOver
|
||||
|
||||
ApplicationInfoProperties(String appInfoXmlPath) {
|
||||
def root = new XmlParser().parse(new File(appInfoXmlPath))
|
||||
majorVersion = root.version.first().@major
|
||||
minorVersion = root.version.first().@minor
|
||||
isEAP = Boolean.parseBoolean(root.version.first().@eap)
|
||||
def installOverTag = root."install-over".first()
|
||||
installOver = new InstallOverProperties(minBuild: installOverTag.@minbuild, maxBuild: installOverTag.@maxbuild, version: installOverTag.@version)
|
||||
}
|
||||
}
|
||||
|
||||
@Immutable
|
||||
class InstallOverProperties {
|
||||
final String minBuild
|
||||
final String maxBuild
|
||||
final String version
|
||||
}
|
||||
@@ -23,7 +23,7 @@ class MacDistributionBuilder {
|
||||
JpsGantProjectBuilder projectBuilder
|
||||
MacHostProperties macHostProperties
|
||||
/**
|
||||
* Directory where IntelliJ IDEA community sources are located
|
||||
* Path to a directory where IntelliJ IDEA community sources are located
|
||||
*/
|
||||
String communityHome
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,184 @@
|
||||
import com.intellij.openapi.util.SystemInfoRt
|
||||
import org.codehaus.gant.GantBuilder
|
||||
import org.jetbrains.jps.gant.JpsGantProjectBuilder
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
class WinInstallerBuilder {
|
||||
GantBuilder ant
|
||||
JpsGantProjectBuilder projectBuilder
|
||||
ApplicationInfoProperties applicationInfo
|
||||
/**
|
||||
* Path to a directory where project sources are located. It will be used to replace 'BASE_DIR' in *.nsi files.
|
||||
*/
|
||||
String baseDirectory
|
||||
/**
|
||||
* Path to a directory where IntelliJ IDEA community sources are located
|
||||
*/
|
||||
String communityHome
|
||||
/**
|
||||
* Path to a directory where artifacts are stored
|
||||
*/
|
||||
String artifactsPath
|
||||
/**
|
||||
* Path to a directory where temporary files can be stored
|
||||
*/
|
||||
String sandboxPath
|
||||
/**
|
||||
* Prefix for the output file name. The value of buildNumber will be appended to this prefix.
|
||||
*/
|
||||
String outNamePrefix
|
||||
/**
|
||||
* Short build number without product code (e.g. 142.239)
|
||||
*/
|
||||
String buildNumber
|
||||
/**
|
||||
* Name which will be used for default config/system paths, should include the product name and version. E.g. for IntelliJ Ultimate 16 it is
|
||||
* 'IntelliJIdea16', so the settings and system files will be stored in $USER_HOME/.IntelliJIdea16 by default.
|
||||
*/
|
||||
String systemSelector
|
||||
/**
|
||||
* Determines whether tools.jar should be included to the bundled JDK
|
||||
*/
|
||||
boolean includeToolsJar = true
|
||||
boolean associateIpr = true
|
||||
/**
|
||||
* Path to a JDK 8 zip file which should be bundled with the application
|
||||
*/
|
||||
String winJDKZipPath
|
||||
|
||||
/**
|
||||
* Builds .exe installer. If build/lib/jet-sign.jar exists in baseDirectory it will be used to sign the created .exe file.
|
||||
*
|
||||
* @param pathsToInclude list of paths to directories which contents should be included to the product distribution
|
||||
* @param stringsFile path to *.nsi file where installers variables are defined (use build/conf/nsis/stringsCE.nsi as a reference)
|
||||
* @param pathsFile path to *.nsi file where installers path variables are defined (use build/conf/nsis/pathsCE.nsi as a reference)
|
||||
* @return path to the created installer file
|
||||
*/
|
||||
def buildInstaller(List<String> pathsToInclude, String stringsFile, String pathsFile) {
|
||||
if (!SystemInfoRt.isWindows) {
|
||||
projectBuilder.warning("Windows installer can be built only under Windows")
|
||||
return null
|
||||
}
|
||||
|
||||
projectBuilder.stage("Building Windows installer")
|
||||
String outFileName = "${outNamePrefix}${buildNumber}"
|
||||
ant.taskdef(name: "nsis", classname: "com.intellij.internalUtilities.ant.NsiFiles", classpath: "$communityHome/build/lib/NsiFiles.jar")
|
||||
|
||||
def box = sandboxPath
|
||||
ant.mkdir(dir: "$box/bin")
|
||||
ant.mkdir(dir: "$box/nsiconf")
|
||||
|
||||
if (winJDKZipPath != null) {
|
||||
ant.mkdir(dir: "$box/jre")
|
||||
ant.unzip(dest: "$box/jre", src: winJDKZipPath)
|
||||
|
||||
ant.copy(todir: "$box/bin") {
|
||||
fileset(dir: "$box/jre/jre/bin") {
|
||||
include(name: "msvcr71.dll")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ant.copy(todir: "$box/nsiconf") {
|
||||
fileset(dir: "$communityHome/build/conf/nsis") {
|
||||
include(name: "*")
|
||||
exclude(name: "version*")
|
||||
exclude(name: "strings*")
|
||||
exclude(name: "paths*")
|
||||
}
|
||||
}
|
||||
|
||||
if (applicationInfo.isEAP) {
|
||||
ant.copy(file: "$communityHome/build/conf/nsis/version.eap.nsi",
|
||||
tofile: "$box/nsiconf/version.nsi", overwrite: true)
|
||||
}
|
||||
else {
|
||||
ant.copy(file: "$communityHome/build/conf/nsis/version.nsi",
|
||||
tofile: "$box/nsiconf/version.nsi", overwrite: true)
|
||||
}
|
||||
ant.copy(file: pathsFile, toFile: "$box/nsiconf/paths.nsi", overwrite: true)
|
||||
|
||||
ant.nsis(instfile: "$box/nsiconf/idea_win.nsh", uninstfile: "$box/nsiconf/unidea_win.nsh") {
|
||||
pathsToInclude.each {
|
||||
ant.fileset(dir: it, includes: "**/*") {
|
||||
exclude(name: "**/idea.properties")
|
||||
exclude(name: "**/*.vmoptions")
|
||||
}
|
||||
}
|
||||
ant.fileset(dir: box, includes: "bin/msvcr71.dll")
|
||||
if (winJDKZipPath != null) {
|
||||
ant.fileset(dir: box, includes: "jre/**/*")
|
||||
if (includeToolsJar) {
|
||||
ant.fileset(dir: box) {
|
||||
include(name: "jre/lib/tools.jar")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ant.copy(file: stringsFile, toFile: "$box/nsiconf/strings.nsi", overwrite: true)
|
||||
ant.replace(file: "$box/nsiconf/strings.nsi") {
|
||||
replacefilter(token: "__VERSION_MAJOR__", value: applicationInfo.majorVersion)
|
||||
replacefilter(token: "__VERSION_MINOR__", value: applicationInfo.minorVersion)
|
||||
}
|
||||
|
||||
ant.replace(file: "$box/nsiconf/version.nsi") {
|
||||
replacefilter(token: "__BUILD_NUMBER__", value: buildNumber)
|
||||
replacefilter(token: "__VERSION_MAJOR__", value: applicationInfo.majorVersion)
|
||||
replacefilter(token: "__VERSION_MINOR__", value: applicationInfo.minorVersion)
|
||||
replacefilter(token: "__MIN_UPGRADE_BUILD__", value: applicationInfo.installOver.minBuild)
|
||||
replacefilter(token: "__MAX_UPGRADE_BUILD__", value: applicationInfo.installOver.maxBuild)
|
||||
replacefilter(token: "__UPGRADE_VERSION__", value: applicationInfo.installOver.version)
|
||||
replacefilter(token: "__PRODUCT_PATHS_SELECTOR__", value: systemSelector)
|
||||
}
|
||||
|
||||
ant.unzip(src: "$communityHome/build/tools/NSIS.zip", dest: box)
|
||||
ant.exec(command: "\"${box}/NSIS/makensis.exe\"" +
|
||||
" /DBASE_DIR=\"$baseDirectory\"" +
|
||||
" /DCOMMUNITY_DIR=\"$communityHome\"" +
|
||||
" /DIPR=\"${associateIpr}\"" +
|
||||
" /DOUT_FILE=\"${outFileName}\"" +
|
||||
" /DOUT_DIR=\"$artifactsPath\"" +
|
||||
" \"${box}/nsiconf/idea.nsi\"")
|
||||
|
||||
def installerPath = "$artifactsPath/${outFileName}.exe"
|
||||
if (!new File(installerPath).exists()) {
|
||||
projectBuilder.error("Installer wasn't created.")
|
||||
}
|
||||
|
||||
def signJarPath = "$baseDirectory/build/lib/jet-sign.jar"
|
||||
if (new File(signJarPath).exists()) {
|
||||
projectBuilder.stage("Signing $installerPath")
|
||||
ant.taskdef(name: "jet-sign", classname: "jetbrains.sign.JetSignTask") {
|
||||
classpath(path: signJarPath)
|
||||
}
|
||||
ant."jet-sign"() {
|
||||
ant.fileset(dir: artifactsPath) {
|
||||
include(name: "${outFileName}.exe")
|
||||
}
|
||||
}
|
||||
projectBuilder.stage("Signing done")
|
||||
}
|
||||
else {
|
||||
projectBuilder.warning("$signJarPath not found, installer won't be signed")
|
||||
}
|
||||
return installerPath
|
||||
}
|
||||
}
|
||||
Binary file not shown.
+10
-14
@@ -30,6 +30,7 @@ import java.util.*;
|
||||
/**
|
||||
* Produces equations for inference of @Contract(pure=true) annotations.
|
||||
* Scala source at https://github.com/ilya-klyuchnikov/faba
|
||||
* Algorithm: https://github.com/ilya-klyuchnikov/faba/blob/ef1c15b4758517652e939f67099bbec0260e9e68/notes/purity.md
|
||||
*/
|
||||
public class PurityAnalysis {
|
||||
static final Set<EffectQuantum> topEffect = Collections.singleton(EffectQuantum.TopEffectQuantum);
|
||||
@@ -444,7 +445,11 @@ final class HardCodedPurity {
|
||||
}
|
||||
|
||||
static Set<EffectQuantum> getHardCodedSolution(HKey key) {
|
||||
// TODO
|
||||
// TODO: implement the logic as in https://github.com/ilya-klyuchnikov/faba/blob/2ffab410416e0a9f8e35d5071df50bcf27b1e149/src/main/scala/asm/purity.scala#L238
|
||||
// The problem with porting logic from Scala version "as is" is that in Scala version original keys (Key) are used.
|
||||
// Here (in IDEA) the hashed keys (HKey) are used. In a general hashed keys may lead to collisions.
|
||||
// So in order to port the logic, hardcoded solutions should be used with stable keys,
|
||||
// that is - during analysis - com.intellij.codeInspection.bytecodeAnalysis.DataInterpreter.naryOperation
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -493,7 +498,7 @@ final class PuritySolver {
|
||||
}
|
||||
else {
|
||||
propagateKeys = new HKey[]{key.mkStable(), key};
|
||||
propagateEffects = new Set[]{effects, mkUnstableEffects(key, effects)};
|
||||
propagateEffects = new Set[]{effects, mkUnstableEffects(key)};
|
||||
}
|
||||
for (int i = 0; i < propagateKeys.length; i++) {
|
||||
HKey pKey = propagateKeys[i];
|
||||
@@ -592,17 +597,8 @@ final class PuritySolver {
|
||||
}
|
||||
}
|
||||
|
||||
private static Set mkUnstableEffects(HKey key, Set<HEffectQuantum> effects) {
|
||||
// TODO
|
||||
return PurityAnalysis.topHEffect;
|
||||
/*
|
||||
Set<EffectQuantum> effects1 = HardCodedPurity.getHardCodedSolution(key);
|
||||
if (effects1 != null) {
|
||||
return effects;
|
||||
}
|
||||
else {
|
||||
return PurityAnalysis.topHEffect;
|
||||
}
|
||||
*/
|
||||
private static Set mkUnstableEffects(HKey key) {
|
||||
Set<EffectQuantum> hardcodedEffects = HardCodedPurity.getHardCodedSolution(key);
|
||||
return hardcodedEffects == null ? PurityAnalysis.topHEffect : hardcodedEffects;
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,6 @@ import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.codeInsight.CodeInsightUtil;
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInsight.actions.OptimizeImportsProcessor;
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
|
||||
import com.intellij.codeInsight.daemon.QuickFixBundle;
|
||||
import com.intellij.codeInsight.hint.QuestionAction;
|
||||
import com.intellij.ide.util.DefaultPsiElementCellRenderer;
|
||||
@@ -267,17 +266,6 @@ public class AddImportAction implements QuestionAction {
|
||||
myEditor.getCaretModel().moveToLogicalPosition(new LogicalPosition(pos2.line, newCol));
|
||||
myEditor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
|
||||
}
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!myProject.isDisposed() && myProject.isOpen()) {
|
||||
DaemonCodeAnalyzer daemonCodeAnalyzer = DaemonCodeAnalyzer.getInstance(myProject);
|
||||
if (daemonCodeAnalyzer != null) {
|
||||
daemonCodeAnalyzer.updateVisibleHighlighters(myEditor);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void bindReference(PsiReference ref, PsiClass targetClass) {
|
||||
|
||||
+57
-146
@@ -19,42 +19,32 @@ import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInsight.JavaProjectCodeInsightSettings;
|
||||
import com.intellij.codeInsight.completion.JavaCompletionUtil;
|
||||
import com.intellij.codeInsight.daemon.QuickFixBundle;
|
||||
import com.intellij.codeInsight.daemon.impl.actions.AddImportAction;
|
||||
import com.intellij.codeInsight.daemon.impl.ShowAutoImportPass;
|
||||
import com.intellij.codeInsight.hint.HintManager;
|
||||
import com.intellij.codeInsight.intention.IntentionAction;
|
||||
import com.intellij.codeInsight.intention.impl.AddSingleMemberStaticImportAction;
|
||||
import com.intellij.ide.util.MethodCellRenderer;
|
||||
import com.intellij.codeInspection.HintAction;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.PopupStep;
|
||||
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.resolve.DefaultParameterTypeInferencePolicy;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.PsiShortNamesCache;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.psi.util.proximity.PsiProximityComparator;
|
||||
import com.intellij.ui.popup.list.ListPopupImpl;
|
||||
import com.intellij.ui.popup.list.PopupListElementRenderer;
|
||||
import com.intellij.util.ArrayUtilRt;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.containers.LinkedMultiMap;
|
||||
import com.intellij.util.containers.MultiMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
public class StaticImportMethodFix implements IntentionAction {
|
||||
public class StaticImportMethodFix implements IntentionAction, HintAction {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.quickfix.StaticImportMethodFix");
|
||||
private final SmartPsiElementPointer<PsiMethodCallExpression> myMethodCall;
|
||||
private List<PsiMethod> candidates;
|
||||
@@ -68,9 +58,7 @@ public class StaticImportMethodFix implements IntentionAction {
|
||||
public String getText() {
|
||||
String text = QuickFixBundle.message("static.import.method.text");
|
||||
if (candidates != null && candidates.size() == 1) {
|
||||
text += " '" + PsiFormatUtil.formatMethod(candidates.get(0), PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_NAME |
|
||||
PsiFormatUtilBase.SHOW_CONTAINING_CLASS |
|
||||
PsiFormatUtilBase.SHOW_FQ_NAME, 0)+"'";
|
||||
text += " '" + getMethodPresentableText() + "'";
|
||||
}
|
||||
else {
|
||||
text += "...";
|
||||
@@ -78,6 +66,13 @@ public class StaticImportMethodFix implements IntentionAction {
|
||||
return text;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String getMethodPresentableText() {
|
||||
return PsiFormatUtil.formatMethod(candidates.get(0), PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_NAME |
|
||||
PsiFormatUtilBase.SHOW_CONTAINING_CLASS |
|
||||
PsiFormatUtilBase.SHOW_FQ_NAME, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getFamilyName() {
|
||||
@@ -91,6 +86,7 @@ public class StaticImportMethodFix implements IntentionAction {
|
||||
&& myMethodCall.getElement() != null
|
||||
&& myMethodCall.getElement().isValid()
|
||||
&& myMethodCall.getElement().getMethodExpression().getQualifierExpression() == null
|
||||
&& myMethodCall.getElement().resolveMethod() == null
|
||||
&& file.getManager().isInProject(file)
|
||||
&& !(candidates == null ? candidates = getMethodsToImport() : candidates).isEmpty()
|
||||
;
|
||||
@@ -263,146 +259,61 @@ public class StaticImportMethodFix implements IntentionAction {
|
||||
@Override
|
||||
public void invoke(@NotNull final Project project, final Editor editor, PsiFile file) {
|
||||
if (!FileModificationService.getInstance().prepareFileForWrite(file)) return;
|
||||
if (candidates.size() == 1) {
|
||||
final PsiMethod toImport = candidates.get(0);
|
||||
doImport(toImport);
|
||||
}
|
||||
else {
|
||||
chooseAndImport(editor, project);
|
||||
}
|
||||
}
|
||||
|
||||
private void doImport(final PsiMethod toImport) {
|
||||
CommandProcessor.getInstance().executeCommand(toImport.getProject(), new Runnable(){
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
PsiMethodCallExpression element = myMethodCall.getElement();
|
||||
if (element != null) {
|
||||
AddSingleMemberStaticImportAction.bindAllClassRefs(element.getContainingFile(), toImport, toImport.getName(), toImport.getContainingClass());
|
||||
}
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final List<PsiMethod> methodsToImport = getMethodsToImport();
|
||||
if (methodsToImport.isEmpty()) return;
|
||||
createQuestionAction(methodsToImport, project, editor).execute();
|
||||
}
|
||||
}, getText(), this);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private void chooseAndImport(Editor editor, final Project project) {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
doImport(candidates.get(0));
|
||||
return;
|
||||
@NotNull
|
||||
private StaticImportMethodQuestionAction createQuestionAction(List<PsiMethod> methodsToImport, @NotNull Project project, Editor editor) {
|
||||
return new StaticImportMethodQuestionAction(project, editor, methodsToImport, myMethodCall);
|
||||
}
|
||||
|
||||
private ImportClassFixBase.Result doFix(Editor editor) {
|
||||
if (candidates.isEmpty()) {
|
||||
return ImportClassFixBase.Result.POPUP_NOT_SHOWN;
|
||||
}
|
||||
final BaseListPopupStep<PsiMethod> step =
|
||||
new BaseListPopupStep<PsiMethod>(QuickFixBundle.message("class.to.import.chooser.title"), candidates) {
|
||||
|
||||
|
||||
final StaticImportMethodQuestionAction action = createQuestionAction(candidates, myMethodCall.getProject(), editor);
|
||||
|
||||
if (candidates.size() == 1) {
|
||||
CommandProcessor.getInstance().runUndoTransparentAction(new Runnable() {
|
||||
@Override
|
||||
public PopupStep onChosen(PsiMethod selectedValue, boolean finalChoice) {
|
||||
if (selectedValue == null) {
|
||||
return FINAL_CHOICE;
|
||||
}
|
||||
|
||||
if (finalChoice) {
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments();
|
||||
LOG.assertTrue(selectedValue.isValid());
|
||||
doImport(selectedValue);
|
||||
return FINAL_CHOICE;
|
||||
}
|
||||
|
||||
String qname = PsiUtil.getMemberQualifiedName(selectedValue);
|
||||
if (qname == null) return FINAL_CHOICE;
|
||||
List<String> excludableStrings = AddImportAction.getAllExcludableStrings(qname);
|
||||
return new BaseListPopupStep<String>(null, excludableStrings) {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getTextFor(String value) {
|
||||
return "Exclude '" + value + "' from auto-import";
|
||||
}
|
||||
|
||||
@Override
|
||||
public PopupStep onChosen(String selectedValue, boolean finalChoice) {
|
||||
if (finalChoice) {
|
||||
AddImportAction.excludeFromImport(project, selectedValue);
|
||||
}
|
||||
|
||||
return super.onChosen(selectedValue, finalChoice);
|
||||
}
|
||||
};
|
||||
public void run() {
|
||||
action.execute();
|
||||
}
|
||||
});
|
||||
return ImportClassFixBase.Result.CLASS_AUTO_IMPORTED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSubstep(PsiMethod selectedValue) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getTextFor(PsiMethod value) {
|
||||
return ObjectUtils.assertNotNull(value.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getIconFor(PsiMethod aValue) {
|
||||
return aValue.getIcon(0);
|
||||
}
|
||||
};
|
||||
|
||||
final ListPopupImpl popup = new ListPopupImpl(step) {
|
||||
final PopupListElementRenderer rightArrow = new PopupListElementRenderer(this);
|
||||
@Override
|
||||
protected ListCellRenderer getListElementRenderer() {
|
||||
return new MethodCellRenderer(true, PsiFormatUtilBase.SHOW_NAME){
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected TextAttributes getNavigationItemAttributes(Object value) {
|
||||
TextAttributes attrs = super.getNavigationItemAttributes(value);
|
||||
if (value instanceof PsiMethod && !((PsiMethod)value).isDeprecated()) {
|
||||
PsiClass psiClass = ((PsiMethod)value).getContainingClass();
|
||||
if (psiClass != null && psiClass.isDeprecated()) {
|
||||
return TextAttributes.merge(attrs, super.getNavigationItemAttributes(psiClass));
|
||||
}
|
||||
}
|
||||
return attrs;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DefaultListCellRenderer getRightCellRenderer(final Object value) {
|
||||
final DefaultListCellRenderer moduleRenderer = super.getRightCellRenderer(value);
|
||||
return new DefaultListCellRenderer(){
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
if (moduleRenderer != null) {
|
||||
Component moduleComponent = moduleRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
if (!isSelected) {
|
||||
moduleComponent.setBackground(getBackgroundColor(value));
|
||||
}
|
||||
panel.add(moduleComponent, BorderLayout.CENTER);
|
||||
}
|
||||
rightArrow.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
Component rightArrowComponent = rightArrow.getNextStepLabel();
|
||||
panel.add(rightArrowComponent, BorderLayout.EAST);
|
||||
return panel;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
popup.showInBestPositionFor(editor);
|
||||
String hintText = ShowAutoImportPass.getMessage(candidates.size() > 1, getMethodPresentableText());
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode() && !HintManager.getInstance().hasShownHintsThatWillHideByOtherHint(true)) {
|
||||
final PsiMethodCallExpression element = myMethodCall.getElement();
|
||||
final TextRange textRange = element.getTextRange();
|
||||
HintManager.getInstance().showQuestionHint(editor, hintText,
|
||||
textRange.getStartOffset(),
|
||||
textRange.getEndOffset(), action);
|
||||
}
|
||||
return ImportClassFixBase.Result.POPUP_SHOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean startInWriteAction() {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean showHint(@NotNull Editor editor) {
|
||||
final PsiMethodCallExpression callExpression = myMethodCall.getElement();
|
||||
if (callExpression == null || callExpression.getMethodExpression().getQualifierExpression() != null) {
|
||||
return false;
|
||||
}
|
||||
ImportClassFixBase.Result result = doFix(editor);
|
||||
return result == ImportClassFixBase.Result.POPUP_SHOWN || result == ImportClassFixBase.Result.CLASS_AUTO_IMPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
+217
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.codeInsight.daemon.impl.quickfix;
|
||||
|
||||
import com.intellij.codeInsight.daemon.QuickFixBundle;
|
||||
import com.intellij.codeInsight.daemon.impl.actions.AddImportAction;
|
||||
import com.intellij.codeInsight.hint.QuestionAction;
|
||||
import com.intellij.codeInsight.intention.impl.AddSingleMemberStaticImportAction;
|
||||
import com.intellij.ide.util.MethodCellRenderer;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.PopupStep;
|
||||
import com.intellij.openapi.ui.popup.util.BaseListPopupStep;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiFormatUtilBase;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.ui.popup.list.ListPopupImpl;
|
||||
import com.intellij.ui.popup.list.PopupListElementRenderer;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.util.List;
|
||||
|
||||
public class StaticImportMethodQuestionAction implements QuestionAction {
|
||||
private static final Logger LOG = Logger.getInstance("#" + StaticImportMethodQuestionAction.class.getName());
|
||||
private final Project myProject;
|
||||
private final Editor myEditor;
|
||||
private List<PsiMethod> myCandidates;
|
||||
private final SmartPsiElementPointer<PsiMethodCallExpression> myMethodCall;
|
||||
|
||||
public StaticImportMethodQuestionAction(Project project,
|
||||
Editor editor,
|
||||
List<PsiMethod> candidates,
|
||||
SmartPsiElementPointer<PsiMethodCallExpression> methodCall) {
|
||||
myProject = project;
|
||||
myEditor = editor;
|
||||
myCandidates = candidates;
|
||||
myMethodCall = methodCall;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean execute() {
|
||||
PsiDocumentManager.getInstance(myProject).commitAllDocuments();
|
||||
|
||||
final PsiMethodCallExpression element = myMethodCall.getElement();
|
||||
if (element == null || !element.isValid()){
|
||||
return false;
|
||||
}
|
||||
|
||||
for (PsiMethod targetMethod : myCandidates) {
|
||||
if (!targetMethod.isValid()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (myCandidates.size() == 1){
|
||||
doImport(myCandidates.get(0));
|
||||
}
|
||||
else{
|
||||
chooseAndImport(myEditor, myProject);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void doImport(final PsiMethod toImport) {
|
||||
final Project project = toImport.getProject();
|
||||
CommandProcessor.getInstance().executeCommand(project, new Runnable(){
|
||||
@Override
|
||||
public void run() {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
PsiMethodCallExpression element = myMethodCall.getElement();
|
||||
if (element != null) {
|
||||
AddSingleMemberStaticImportAction.bindAllClassRefs(element.getContainingFile(), toImport, toImport.getName(), toImport.getContainingClass());
|
||||
}
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
LOG.error(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}, QuickFixBundle.message("add.import"), this);
|
||||
|
||||
}
|
||||
|
||||
private void chooseAndImport(final Editor editor, final Project project) {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
doImport(myCandidates.get(0));
|
||||
return;
|
||||
}
|
||||
final BaseListPopupStep<PsiMethod> step =
|
||||
new BaseListPopupStep<PsiMethod>(QuickFixBundle.message("method.to.import.chooser.title"), myCandidates) {
|
||||
|
||||
@Override
|
||||
public PopupStep onChosen(PsiMethod selectedValue, boolean finalChoice) {
|
||||
if (selectedValue == null) {
|
||||
return FINAL_CHOICE;
|
||||
}
|
||||
|
||||
if (finalChoice) {
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments();
|
||||
LOG.assertTrue(selectedValue.isValid());
|
||||
doImport(selectedValue);
|
||||
return FINAL_CHOICE;
|
||||
}
|
||||
|
||||
String qname = PsiUtil.getMemberQualifiedName(selectedValue);
|
||||
if (qname == null) return FINAL_CHOICE;
|
||||
List<String> excludableStrings = AddImportAction.getAllExcludableStrings(qname);
|
||||
return new BaseListPopupStep<String>(null, excludableStrings) {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getTextFor(String value) {
|
||||
return "Exclude '" + value + "' from auto-import";
|
||||
}
|
||||
|
||||
@Override
|
||||
public PopupStep onChosen(String selectedValue, boolean finalChoice) {
|
||||
if (finalChoice) {
|
||||
AddImportAction.excludeFromImport(project, selectedValue);
|
||||
}
|
||||
|
||||
return super.onChosen(selectedValue, finalChoice);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSubstep(PsiMethod selectedValue) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getTextFor(PsiMethod value) {
|
||||
return ObjectUtils.assertNotNull(value.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getIconFor(PsiMethod aValue) {
|
||||
return aValue.getIcon(0);
|
||||
}
|
||||
};
|
||||
|
||||
final ListPopupImpl popup = new ListPopupImpl(step) {
|
||||
final PopupListElementRenderer rightArrow = new PopupListElementRenderer(this);
|
||||
@Override
|
||||
protected ListCellRenderer getListElementRenderer() {
|
||||
return new MethodCellRenderer(true, PsiFormatUtilBase.SHOW_NAME){
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected TextAttributes getNavigationItemAttributes(Object value) {
|
||||
TextAttributes attrs = super.getNavigationItemAttributes(value);
|
||||
if (value instanceof PsiMethod && !((PsiMethod)value).isDeprecated()) {
|
||||
PsiClass psiClass = ((PsiMethod)value).getContainingClass();
|
||||
if (psiClass != null && psiClass.isDeprecated()) {
|
||||
return TextAttributes.merge(attrs, super.getNavigationItemAttributes(psiClass));
|
||||
}
|
||||
}
|
||||
return attrs;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DefaultListCellRenderer getRightCellRenderer(final Object value) {
|
||||
final DefaultListCellRenderer moduleRenderer = super.getRightCellRenderer(value);
|
||||
return new DefaultListCellRenderer(){
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
|
||||
JPanel panel = new JPanel(new BorderLayout());
|
||||
if (moduleRenderer != null) {
|
||||
Component moduleComponent = moduleRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
if (!isSelected) {
|
||||
moduleComponent.setBackground(getBackgroundColor(value));
|
||||
}
|
||||
panel.add(moduleComponent, BorderLayout.CENTER);
|
||||
}
|
||||
rightArrow.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
|
||||
Component rightArrowComponent = rightArrow.getNextStepLabel();
|
||||
panel.add(rightArrowComponent, BorderLayout.EAST);
|
||||
return panel;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
popup.showInBestPositionFor(editor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -122,7 +122,13 @@ public class PsiMethodReferenceUtil {
|
||||
PsiSubstitutor substitutor = PsiSubstitutor.EMPTY;
|
||||
final PsiExpression expression = methodReferenceExpression.getQualifierExpression();
|
||||
if (expression != null) {
|
||||
final PsiType expressionType = replaceArrayType(expression.getType(), expression);
|
||||
PsiType expressionType = expression.getType();
|
||||
if (expressionType instanceof PsiCapturedWildcardType) {
|
||||
expressionType = ((PsiCapturedWildcardType)expressionType).getUpperBound();
|
||||
}
|
||||
else {
|
||||
expressionType = replaceArrayType(expressionType, expression);
|
||||
}
|
||||
PsiClassType.ClassResolveResult result = PsiUtil.resolveGenericsClassInType(expressionType);
|
||||
containingClass = result.getElement();
|
||||
if (containingClass != null) {
|
||||
|
||||
+3
-2
@@ -26,6 +26,7 @@ import com.intellij.psi.util.MethodSignature;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -259,7 +260,7 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
|
||||
return psiSubstitutor;
|
||||
}
|
||||
|
||||
public static PsiSubstitutor getParameterizedTypeSubstitutor(PsiClass qContainingClass, PsiType pType) {
|
||||
public static PsiSubstitutor getParameterizedTypeSubstitutor(PsiClass qContainingClass, @NotNull PsiType pType) {
|
||||
if (pType instanceof PsiIntersectionType) {
|
||||
for (PsiType type : ((PsiIntersectionType)pType).getConjuncts()) {
|
||||
PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(type);
|
||||
@@ -271,7 +272,7 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
|
||||
|
||||
PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(pType);
|
||||
PsiClass paramClass = resolveResult.getElement();
|
||||
LOG.assertTrue(paramClass != null);
|
||||
LOG.assertTrue(paramClass != null, pType.getCanonicalText());
|
||||
PsiSubstitutor psiSubstitutor = TypeConversionUtil.getClassSubstitutor(qContainingClass, paramClass, resolveResult.getSubstitutor());
|
||||
LOG.assertTrue(psiSubstitutor != null);
|
||||
return psiSubstitutor;
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
|
||||
final class Test {
|
||||
static <T> T create(Iterable<? extends T> iterable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static <T> void testError(Iterable<? extends T> iterable) {
|
||||
Runnable r = create(iterable)::toString;
|
||||
}
|
||||
|
||||
}
|
||||
+4
@@ -482,6 +482,10 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testQualifierOfCapturedWildcardType() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,5 @@
|
||||
<orderEntry type="module" module-name="vcs-api" />
|
||||
<orderEntry type="library" scope="TEST" name="KotlinJavaRuntime" level="project" />
|
||||
<orderEntry type="library" scope="TEST" name="assertJ" level="project" />
|
||||
<orderEntry type="module" module-name="test-framework-java8" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -18,6 +18,5 @@
|
||||
<orderEntry type="module" module-name="eclipse" scope="TEST" />
|
||||
<orderEntry type="module" module-name="configuration-store-impl" />
|
||||
<orderEntry type="module" module-name="util-tests" scope="TEST" />
|
||||
<orderEntry type="module" module-name="test-framework-java8" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2012 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.
|
||||
@@ -32,8 +32,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.io.File;
|
||||
|
||||
public class PathUtil {
|
||||
private PathUtil() {
|
||||
}
|
||||
private PathUtil() { }
|
||||
|
||||
@Nullable
|
||||
public static String getLocalPath(@Nullable VirtualFile file) {
|
||||
@@ -112,12 +111,15 @@ public class PathUtil {
|
||||
return PathUtilRt.isValidFileName(fileName);
|
||||
}
|
||||
|
||||
public static boolean isValidFileName(@NotNull String fileName, boolean strict) {
|
||||
return PathUtilRt.isValidFileName(fileName, strict);
|
||||
}
|
||||
|
||||
@Contract("null -> null; !null -> !null")
|
||||
public static String toSystemIndependentName(@Nullable String path) {
|
||||
return path == null ? null : FileUtilRt.toSystemIndependentName(path);
|
||||
}
|
||||
|
||||
|
||||
@Contract("null -> null; !null -> !null")
|
||||
public static String toSystemDependentName(@Nullable String path) {
|
||||
return path == null ? null : FileUtilRt.toSystemDependentName(path);
|
||||
@@ -136,6 +138,6 @@ public class PathUtil {
|
||||
|
||||
@NotNull
|
||||
public static String makeFileName(@NotNull String name, @Nullable String extension) {
|
||||
return name + (StringUtil.isEmpty(extension) ? "" : "." + extension);
|
||||
return StringUtil.isEmpty(extension) ? name : name + '.' + extension;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -110,7 +110,7 @@ public class CommonRefactoringUtil {
|
||||
return JBIterable.from(elements).transform(new Function<PsiElement, PsiElement>() {
|
||||
@Override
|
||||
public PsiElement fun(PsiElement e) {
|
||||
return e instanceof PsiFileSystemItem ? e.getParent() : e;
|
||||
return e instanceof PsiFileSystemItem && e.getParent() != null ? e.getParent() : e;
|
||||
}
|
||||
}).toSet();
|
||||
}
|
||||
|
||||
+24
-29
@@ -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.
|
||||
@@ -23,7 +23,7 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.help.HelpManager;
|
||||
import com.intellij.openapi.keymap.KeymapUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -31,6 +31,8 @@ import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.DialogWrapperPeer;
|
||||
import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.ui.TextComponentAccessor;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
@@ -51,7 +53,6 @@ import javax.swing.*;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.event.DocumentListener;
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
public class CopyFilesOrDirectoriesDialog extends DialogWrapper {
|
||||
@@ -102,29 +103,25 @@ public class CopyFilesOrDirectoriesDialog extends DialogWrapper {
|
||||
String text;
|
||||
if (elements[0] instanceof PsiFile) {
|
||||
PsiFile file = (PsiFile)elements[0];
|
||||
VirtualFile virtualFile = file.getVirtualFile();
|
||||
String url = shortenPath(virtualFile);
|
||||
text = RefactoringBundle.message(doClone ? "copy.files.clone.file.0" : "copy.files.copy.file.0", url);
|
||||
// keep extensions (dots) and spaces, e.g. fragment file name will be "HTML Fragment (my.sql_61).html"
|
||||
// and leave ordinary file name AS IS
|
||||
String fileName = PathUtil.suggestFileName(file.getName(), true, true);
|
||||
if (StringUtil.isEmpty(virtualFile.getExtension())) {
|
||||
LanguageFileType type = file.getLanguage().getAssociatedFileType();
|
||||
fileName = PathUtil.makeFileName(fileName, ObjectUtils.notNull(type, file.getFileType()).getDefaultExtension());
|
||||
VirtualFile vFile = file.getVirtualFile();
|
||||
text = RefactoringBundle.message(doClone ? "copy.files.clone.file.0" : "copy.files.copy.file.0", shortenPath(vFile));
|
||||
String fileName = vFile.isInLocalFileSystem() ? vFile.getName() : PathUtil.suggestFileName(file.getName(), true, true);
|
||||
if (StringUtil.isEmpty(vFile.getExtension())) {
|
||||
FileType type = ObjectUtils.notNull(file.getLanguage().getAssociatedFileType(), file.getFileType());
|
||||
fileName = PathUtil.makeFileName(fileName, type.getDefaultExtension());
|
||||
}
|
||||
myNewNameField.setText(fileName);
|
||||
final int dotIdx = fileName.lastIndexOf(".");
|
||||
if (dotIdx > -1) {
|
||||
int dotIdx = fileName.lastIndexOf('.');
|
||||
if (dotIdx > 0) {
|
||||
myNewNameField.select(0, dotIdx);
|
||||
myNewNameField.putClientProperty(DialogWrapperPeer.HAVE_INITIAL_SELECTION, true);
|
||||
}
|
||||
myFileCopy = true;
|
||||
}
|
||||
else {
|
||||
PsiDirectory directory = (PsiDirectory)elements[0];
|
||||
String url = shortenPath(directory.getVirtualFile());
|
||||
text = RefactoringBundle.message(doClone ? "copy.files.clone.directory.0" : "copy.files.copy.directory.0", url);
|
||||
myNewNameField.setText(directory.getName());
|
||||
VirtualFile vFile = ((PsiDirectory)elements[0]).getVirtualFile();
|
||||
text = RefactoringBundle.message(doClone ? "copy.files.clone.directory.0" : "copy.files.copy.directory.0", shortenPath(vFile));
|
||||
myNewNameField.setText(vFile.getName());
|
||||
}
|
||||
myInformationLabel.setText(text);
|
||||
}
|
||||
@@ -258,7 +255,7 @@ public class CopyFilesOrDirectoriesDialog extends DialogWrapper {
|
||||
return;
|
||||
}
|
||||
|
||||
if (myFileCopy && !PathUtil.isValidFileName(newName)) {
|
||||
if (myFileCopy && !PathUtil.isValidFileName(newName, SystemInfo.isWindows)) {
|
||||
Messages.showErrorDialog(myNewNameField, "Name is not a valid file name");
|
||||
return;
|
||||
}
|
||||
@@ -283,8 +280,8 @@ public class CopyFilesOrDirectoriesDialog extends DialogWrapper {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
myTargetDirectory =
|
||||
DirectoryUtil.mkdirs(PsiManager.getInstance(myProject), targetDirectoryName.replace(File.separatorChar, '/'));
|
||||
String path = FileUtil.toSystemIndependentName(targetDirectoryName);
|
||||
myTargetDirectory = DirectoryUtil.mkdirs(PsiManager.getInstance(myProject), path);
|
||||
}
|
||||
catch (IncorrectOperationException ignored) { }
|
||||
}
|
||||
@@ -302,15 +299,13 @@ public class CopyFilesOrDirectoriesDialog extends DialogWrapper {
|
||||
}
|
||||
|
||||
private void validateOKButton() {
|
||||
if (myShowDirectoryField) {
|
||||
if (myTargetDirectoryField.getChildComponent().getText().length() == 0) {
|
||||
setOKActionEnabled(false);
|
||||
return;
|
||||
}
|
||||
if (myShowDirectoryField && myTargetDirectoryField.getChildComponent().getText().length() == 0) {
|
||||
setOKActionEnabled(false);
|
||||
return;
|
||||
}
|
||||
if (myShowNewNameField) {
|
||||
final String newName = getNewName();
|
||||
if (newName.length() == 0 || myFileCopy && !PathUtil.isValidFileName(newName)) {
|
||||
String newName = getNewName();
|
||||
if (newName.length() == 0 || myFileCopy && !PathUtil.isValidFileName(newName, SystemInfo.isWindows)) {
|
||||
setOKActionEnabled(false);
|
||||
return;
|
||||
}
|
||||
@@ -322,4 +317,4 @@ public class CopyFilesOrDirectoriesDialog extends DialogWrapper {
|
||||
protected void doHelpAction() {
|
||||
HelpManager.getInstance().invokeHelp("refactoring.copyClass");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,509 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.ui.components;
|
||||
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.components.JBScrollBar.Alignment;
|
||||
import com.intellij.util.ui.JBInsets;
|
||||
import com.intellij.util.ui.JBUI;
|
||||
import com.intellij.util.ui.RegionPainter;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import javax.swing.plaf.ScrollBarUI;
|
||||
import java.beans.PropertyChangeEvent;
|
||||
import java.beans.PropertyChangeListener;
|
||||
|
||||
import static java.awt.Adjustable.VERTICAL;
|
||||
|
||||
/**
|
||||
* @author Sergey.Malenkov
|
||||
*/
|
||||
abstract class AbstractScrollBarUI extends ScrollBarUI {
|
||||
static final Key<RegionPainter<Object>> LEADING_AREA = Key.create("PLAIN_SCROLL_BAR_UI_LEADING_AREA");//TODO:support
|
||||
|
||||
private static final JBColor TRACK_BACKGROUND = new JBColor(0xF5F5F5, 0x3c3f41);
|
||||
private static final JBColor TRACK_FOREGROUND = new JBColor(0xE6E6E6, 0x3C3F41);
|
||||
|
||||
private final Listener myListener = new Listener();
|
||||
private final Timer myScrollTimer = new Timer(60, myListener);
|
||||
|
||||
private final Rectangle myThumbBounds = new Rectangle();
|
||||
private final Rectangle myTrackBounds = new Rectangle();
|
||||
private final Rectangle myLeadingBounds = new Rectangle();
|
||||
|
||||
private JScrollBar myScrollBar;
|
||||
|
||||
private boolean isTrackVisible;
|
||||
private boolean isValueCached;
|
||||
private int myCachedValue;
|
||||
|
||||
abstract int getThickness();
|
||||
|
||||
abstract int getMinimalThickness();
|
||||
|
||||
abstract void onTrackHover(boolean hover);
|
||||
|
||||
abstract void onThumbHover(boolean hover);
|
||||
|
||||
abstract void paintTrack(Graphics2D g, int x, int y, int width, int height, JComponent c);
|
||||
|
||||
abstract void paintThumb(Graphics2D g, int x, int y, int width, int height, JComponent c);
|
||||
|
||||
void setTrackVisible(boolean trackVisible) {
|
||||
if (isTrackVisible != trackVisible) {
|
||||
isTrackVisible = trackVisible;
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
void repaint() {
|
||||
if (myScrollBar != null) myScrollBar.repaint();
|
||||
}
|
||||
|
||||
void repaint(int x, int y, int width, int height) {
|
||||
if (myScrollBar != null) myScrollBar.repaint(x, y, width, height);
|
||||
}
|
||||
|
||||
int scale(int value) {
|
||||
value = JBUI.scale(value);
|
||||
//noinspection EnumSwitchStatementWhichMissesCases
|
||||
switch (UIUtil.getComponentStyle(myScrollBar)) {
|
||||
case LARGE:
|
||||
return (int)(value * 1.15);
|
||||
case SMALL:
|
||||
return (int)(value * 0.857);
|
||||
case MINI:
|
||||
return (int)(value * 0.714);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void installUI(JComponent c) {
|
||||
myScrollBar = (JScrollBar)c;
|
||||
myScrollBar.setBackground(TRACK_BACKGROUND);
|
||||
myScrollBar.setForeground(TRACK_FOREGROUND);
|
||||
myScrollBar.setFocusable(false);
|
||||
myScrollBar.addMouseListener(myListener);
|
||||
myScrollBar.addMouseMotionListener(myListener);
|
||||
myScrollBar.getModel().addChangeListener(myListener);
|
||||
myScrollBar.addPropertyChangeListener(myListener);
|
||||
myScrollBar.addFocusListener(myListener);
|
||||
myScrollTimer.setInitialDelay(300);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void uninstallUI(JComponent c) {
|
||||
myScrollTimer.stop();
|
||||
myScrollBar.removeFocusListener(myListener);
|
||||
myScrollBar.removePropertyChangeListener(myListener);
|
||||
myScrollBar.getModel().removeChangeListener(myListener);
|
||||
myScrollBar.removeMouseMotionListener(myListener);
|
||||
myScrollBar.removeMouseListener(myListener);
|
||||
myScrollBar = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize(JComponent c) {
|
||||
int thickness = getThickness();
|
||||
Alignment alignment = Alignment.get(c);
|
||||
return alignment == Alignment.LEFT || alignment == Alignment.RIGHT
|
||||
? new Dimension(thickness, thickness * 3)
|
||||
: new Dimension(thickness * 3, thickness);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paint(Graphics g, JComponent c) {
|
||||
Alignment alignment = Alignment.get(c);
|
||||
if (alignment != null && g instanceof Graphics2D) {
|
||||
Rectangle bounds = new Rectangle(c.getSize());
|
||||
JBInsets.removeFrom(bounds, c.getInsets());
|
||||
if (c.isOpaque() && c.getParent() instanceof JScrollPane) {
|
||||
g.setColor(c.getForeground());
|
||||
switch (alignment) {
|
||||
case TOP:
|
||||
bounds.height--;
|
||||
g.drawLine(bounds.x, bounds.y + bounds.height, bounds.x + bounds.width, bounds.y + bounds.height);
|
||||
break;
|
||||
case LEFT:
|
||||
bounds.width--;
|
||||
g.drawLine(bounds.x + bounds.width, bounds.y, bounds.x + bounds.width, bounds.y + bounds.height);
|
||||
break;
|
||||
case RIGHT:
|
||||
g.drawLine(bounds.x, bounds.y, bounds.x, bounds.y + bounds.height);
|
||||
bounds.width--;
|
||||
bounds.x++;
|
||||
break;
|
||||
case BOTTOM:
|
||||
g.drawLine(bounds.x, bounds.y, bounds.x + bounds.width, bounds.y);
|
||||
bounds.height--;
|
||||
bounds.y++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (isTrackVisible) {
|
||||
paintTrack((Graphics2D)g, bounds.x, bounds.y, bounds.width, bounds.height, c);
|
||||
}
|
||||
// process a square area before the track
|
||||
RegionPainter<Object> leading = UIUtil.getClientProperty(c, LEADING_AREA);
|
||||
if (leading == null) {
|
||||
myLeadingBounds.setSize(0, 0);
|
||||
}
|
||||
else if (alignment == Alignment.LEFT || alignment == Alignment.RIGHT) {
|
||||
int size = bounds.width;
|
||||
myLeadingBounds.setBounds(bounds.x, bounds.y, size, size);
|
||||
leading.paint((Graphics2D)g, bounds.x, bounds.y, size, size, null);
|
||||
bounds.height -= size;
|
||||
bounds.y += size;
|
||||
}
|
||||
else {
|
||||
int size = bounds.height;
|
||||
myLeadingBounds.setBounds(bounds.x, bounds.y, size, size);
|
||||
leading.paint((Graphics2D)g, bounds.x, bounds.y, size, size, null);
|
||||
bounds.width -= size;
|
||||
bounds.x += size;
|
||||
}
|
||||
// process additional drawing on the track
|
||||
myTrackBounds.setBounds(bounds);
|
||||
RegionPainter<Object> track = UIUtil.getClientProperty(c, JBScrollBar.TRACK);
|
||||
if (track != null && myTrackBounds.width > 0 && myTrackBounds.height > 0) {
|
||||
track.paint((Graphics2D)g, myTrackBounds.x, myTrackBounds.y, myTrackBounds.width, myTrackBounds.height, null);
|
||||
}
|
||||
// process drawing the thumb
|
||||
updateThumbBounds();
|
||||
if (myThumbBounds.width > 0 && myThumbBounds.height > 0) {
|
||||
paintThumb((Graphics2D)g, myThumbBounds.x, myThumbBounds.y, myThumbBounds.width, myThumbBounds.height, c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void updateThumbBounds() {
|
||||
int min = myScrollBar.getMinimum();
|
||||
int max = myScrollBar.getMaximum();
|
||||
int range = max - min;
|
||||
if (range <= 0) {
|
||||
myThumbBounds.setBounds(0, 0, 0, 0);
|
||||
}
|
||||
else if (VERTICAL == myScrollBar.getOrientation()) {
|
||||
int extent = myScrollBar.getVisibleAmount();
|
||||
int height = Math.max(myTrackBounds.height * extent / range, 2 * getThickness());
|
||||
if (myTrackBounds.height <= height) {
|
||||
myThumbBounds.setBounds(0, 0, 0, 0);
|
||||
}
|
||||
else {
|
||||
int value = getValue();
|
||||
int maxY = myTrackBounds.y + myTrackBounds.height - height;
|
||||
int y = (value < max - extent) ? (myTrackBounds.height - height) * (value - min) / (range - extent) : maxY;
|
||||
myThumbBounds.setBounds(myTrackBounds.x, adjust(y, myTrackBounds.y, maxY), myTrackBounds.width, height);
|
||||
}
|
||||
}
|
||||
else {
|
||||
int extent = myScrollBar.getVisibleAmount();
|
||||
int width = Math.max(myTrackBounds.width * extent / range, 2 * getThickness());
|
||||
if (myTrackBounds.width <= width) {
|
||||
myThumbBounds.setBounds(0, 0, 0, 0);
|
||||
}
|
||||
else {
|
||||
int value = getValue();
|
||||
int maxX = myTrackBounds.x + myTrackBounds.width - width;
|
||||
int x = (value < max - extent) ? (myTrackBounds.width - width) * (value - min) / (range - extent) : maxX;
|
||||
myThumbBounds.setBounds(adjust(x, myTrackBounds.x, maxX), myTrackBounds.y, width, myTrackBounds.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getValue() {
|
||||
return isValueCached ? myCachedValue : myScrollBar.getValue();
|
||||
}
|
||||
|
||||
private static int adjust(int value, int min, int max) {
|
||||
return value < min ? min : value > max ? max : value;
|
||||
}
|
||||
|
||||
private final class Listener extends MouseAdapter implements ActionListener, FocusListener, ChangeListener, PropertyChangeListener {
|
||||
private int myOffset;
|
||||
private int myMouseX, myMouseY;
|
||||
private boolean isReversed;
|
||||
private boolean isDragging;
|
||||
private boolean isOverTrack;
|
||||
private boolean isOverThumb;
|
||||
|
||||
private void updateMouse(int x, int y) {
|
||||
if (myTrackBounds.contains(x, y)) {
|
||||
if (!isOverTrack) onTrackHover(isOverTrack = true);
|
||||
boolean hover = myThumbBounds.contains(x, y);
|
||||
if (isOverThumb != hover) onThumbHover(isOverThumb = hover);
|
||||
}
|
||||
else {
|
||||
updateMouseExit();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateMouseExit() {
|
||||
if (isOverThumb) onThumbHover(isOverThumb = false);
|
||||
if (isOverTrack) onTrackHover(isOverTrack = false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent event) {
|
||||
if (myScrollBar == null || !myScrollBar.isEnabled()) return;
|
||||
if (SwingUtilities.isRightMouseButton(event)) return;
|
||||
|
||||
isValueCached = true;
|
||||
myCachedValue = myScrollBar.getValue();
|
||||
myScrollBar.setValueIsAdjusting(true);
|
||||
|
||||
myMouseX = event.getX();
|
||||
myMouseY = event.getY();
|
||||
|
||||
boolean vertical = VERTICAL == myScrollBar.getOrientation();
|
||||
if (myThumbBounds.contains(myMouseX, myMouseY)) {
|
||||
// pressed on the thumb
|
||||
myOffset = vertical ? (myMouseY - myThumbBounds.y) : (myMouseX - myThumbBounds.x);
|
||||
isDragging = true;
|
||||
}
|
||||
else if (isTrackVisible && myTrackBounds.contains(myMouseX, myMouseY)) {
|
||||
// pressed on the track
|
||||
if (SwingUtilities.isMiddleMouseButton(event)) {
|
||||
myOffset = (vertical ? myThumbBounds.height : myThumbBounds.width) / 2;
|
||||
isDragging = true;
|
||||
setValueFrom(event);
|
||||
}
|
||||
else {
|
||||
myScrollTimer.stop();
|
||||
isDragging = false;
|
||||
if (VERTICAL == myScrollBar.getOrientation()) {
|
||||
int y = myThumbBounds.isEmpty() ? myScrollBar.getHeight() / 2 : myThumbBounds.y;
|
||||
isReversed = myMouseY < y;
|
||||
}
|
||||
else {
|
||||
int x = myThumbBounds.isEmpty() ? myScrollBar.getWidth() / 2 : myThumbBounds.x;
|
||||
isReversed = myMouseX < x;
|
||||
if (!myScrollBar.getComponentOrientation().isLeftToRight()) {
|
||||
isReversed = !isReversed;
|
||||
}
|
||||
}
|
||||
scroll(isReversed);
|
||||
startScrollTimerIfNecessary();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseReleased(MouseEvent event) {
|
||||
if (isDragging) updateMouse(event.getX(), event.getY());
|
||||
if (myScrollBar == null || !myScrollBar.isEnabled()) return;
|
||||
if (SwingUtilities.isRightMouseButton(event)) return;
|
||||
isDragging = false;
|
||||
myOffset = 0;
|
||||
myScrollTimer.stop();
|
||||
isValueCached = true;
|
||||
myCachedValue = myScrollBar.getValue();
|
||||
myScrollBar.setValueIsAdjusting(false);
|
||||
repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(MouseEvent event) {
|
||||
if (myScrollBar == null || !myScrollBar.isEnabled()) return;
|
||||
if (myThumbBounds.isEmpty() || SwingUtilities.isRightMouseButton(event)) return;
|
||||
if (isDragging) {
|
||||
setValueFrom(event);
|
||||
}
|
||||
else {
|
||||
myMouseX = event.getX();
|
||||
myMouseY = event.getY();
|
||||
updateMouse(myMouseX, myMouseY);
|
||||
startScrollTimerIfNecessary();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseMoved(MouseEvent event) {
|
||||
if (myScrollBar == null || !myScrollBar.isEnabled()) return;
|
||||
if (!isDragging) updateMouse(event.getX(), event.getY());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseExited(MouseEvent event) {
|
||||
if (myScrollBar == null || !myScrollBar.isEnabled()) return;
|
||||
if (!isDragging) updateMouseExit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent event) {
|
||||
if (myScrollBar == null) {
|
||||
myScrollTimer.stop();
|
||||
}
|
||||
else {
|
||||
scroll(isReversed);
|
||||
if (!myThumbBounds.isEmpty()) {
|
||||
if (isReversed ? !isMouseBeforeThumb() : !isMouseAfterThumb()) {
|
||||
myScrollTimer.stop();
|
||||
}
|
||||
}
|
||||
int value = myScrollBar.getValue();
|
||||
if (isReversed ? value <= myScrollBar.getMinimum() : value >= myScrollBar.getMaximum() - myScrollBar.getVisibleAmount()) {
|
||||
myScrollTimer.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusGained(FocusEvent event) {
|
||||
repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void focusLost(FocusEvent event) {
|
||||
repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent event) {
|
||||
updateThumbBounds();
|
||||
// TODO: update mouse
|
||||
isValueCached = false;
|
||||
repaint();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void propertyChange(PropertyChangeEvent event) {
|
||||
String name = event.getPropertyName();
|
||||
if ("model" == name) {
|
||||
BoundedRangeModel oldModel = (BoundedRangeModel)event.getOldValue();
|
||||
BoundedRangeModel newModel = (BoundedRangeModel)event.getNewValue();
|
||||
oldModel.removeChangeListener(this);
|
||||
newModel.addChangeListener(this);
|
||||
}
|
||||
if ("model" == name || "orientation" == name || "componentOrientation" == name) {
|
||||
repaint();
|
||||
}
|
||||
}
|
||||
|
||||
private void setValueFrom(MouseEvent event) {
|
||||
int x = event.getX();
|
||||
int y = event.getY();
|
||||
|
||||
int thumbMin, thumbMax, thumbPos;
|
||||
if (VERTICAL == myScrollBar.getOrientation()) {
|
||||
thumbMin = myTrackBounds.y;
|
||||
thumbMax = myTrackBounds.y + myTrackBounds.height - myThumbBounds.height;
|
||||
thumbPos = Math.min(thumbMax, Math.max(thumbMin, (y - myOffset)));
|
||||
if (myThumbBounds.y != thumbPos) {
|
||||
int minY = Math.min(myThumbBounds.y, thumbPos);
|
||||
int maxY = Math.max(myThumbBounds.y, thumbPos) + myThumbBounds.height;
|
||||
myThumbBounds.y = thumbPos;
|
||||
repaint(myThumbBounds.x, minY, myThumbBounds.width, maxY - minY);
|
||||
}
|
||||
}
|
||||
else {
|
||||
thumbMin = myTrackBounds.x;
|
||||
thumbMax = myTrackBounds.x + myTrackBounds.width - myThumbBounds.width;
|
||||
thumbPos = Math.min(thumbMax, Math.max(thumbMin, (x - myOffset)));
|
||||
if (myThumbBounds.x != thumbPos) {
|
||||
int minX = Math.min(myThumbBounds.x, thumbPos);
|
||||
int maxX = Math.max(myThumbBounds.x, thumbPos) + myThumbBounds.width;
|
||||
myThumbBounds.x = thumbPos;
|
||||
repaint(minX, myThumbBounds.y, maxX - minX, myThumbBounds.height);
|
||||
}
|
||||
}
|
||||
int valueMin = myScrollBar.getMinimum();
|
||||
int valueMax = myScrollBar.getMaximum() - myScrollBar.getVisibleAmount();
|
||||
// If the thumb has reached the end of the scrollbar, then just set the value to its maximum.
|
||||
// Otherwise compute the value as accurately as possible.
|
||||
boolean isDefaultOrientation = VERTICAL == myScrollBar.getOrientation() || myScrollBar.getComponentOrientation().isLeftToRight();
|
||||
if (thumbPos == thumbMax) {
|
||||
myScrollBar.setValue(isDefaultOrientation ? valueMax : valueMin);
|
||||
}
|
||||
else {
|
||||
int valueRange = valueMax - valueMin;
|
||||
int thumbRange = thumbMax - thumbMin;
|
||||
int thumbValue = isDefaultOrientation
|
||||
? thumbPos - thumbMin
|
||||
: thumbMax - thumbPos;
|
||||
isValueCached = true;
|
||||
myCachedValue = valueMin + valueRange * thumbValue / thumbRange;
|
||||
myScrollBar.setValue(myCachedValue);
|
||||
}
|
||||
if (!isDragging) updateMouse(x, y);
|
||||
}
|
||||
|
||||
private void startScrollTimerIfNecessary() {
|
||||
if (!myScrollTimer.isRunning()) {
|
||||
if (isReversed ? isMouseBeforeThumb() : isMouseAfterThumb()) {
|
||||
myScrollTimer.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isMouseBeforeThumb() {
|
||||
return VERTICAL == myScrollBar.getOrientation()
|
||||
? isMouseOnTop()
|
||||
: myScrollBar.getComponentOrientation().isLeftToRight()
|
||||
? isMouseOnLeft()
|
||||
: isMouseOnRight();
|
||||
}
|
||||
|
||||
private boolean isMouseAfterThumb() {
|
||||
return VERTICAL == myScrollBar.getOrientation()
|
||||
? isMouseOnBottom()
|
||||
: myScrollBar.getComponentOrientation().isLeftToRight()
|
||||
? isMouseOnRight()
|
||||
: isMouseOnLeft();
|
||||
}
|
||||
|
||||
private boolean isMouseOnTop() {
|
||||
return myMouseY < myThumbBounds.y;
|
||||
}
|
||||
|
||||
private boolean isMouseOnLeft() {
|
||||
return myMouseX < myThumbBounds.x;
|
||||
}
|
||||
|
||||
private boolean isMouseOnRight() {
|
||||
return myMouseX > myThumbBounds.x + myThumbBounds.width;
|
||||
}
|
||||
|
||||
private boolean isMouseOnBottom() {
|
||||
return myMouseY > myThumbBounds.y + myThumbBounds.height;
|
||||
}
|
||||
|
||||
private void scroll(boolean reversed) {
|
||||
int delta = myScrollBar.getBlockIncrement(reversed ? -1 : 1);
|
||||
if (reversed) delta = -delta;
|
||||
|
||||
int oldValue = myScrollBar.getValue();
|
||||
int newValue = oldValue + delta;
|
||||
|
||||
if (delta > 0 && newValue < oldValue) {
|
||||
newValue = myScrollBar.getMaximum();
|
||||
}
|
||||
else if (delta < 0 && newValue > oldValue) {
|
||||
newValue = myScrollBar.getMinimum();
|
||||
}
|
||||
if (oldValue != newValue) {
|
||||
myScrollBar.setValue(newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.ui.components;
|
||||
|
||||
import com.intellij.ui.Gray;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.ui.components.JBScrollBar.Alignment;
|
||||
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.Composite;
|
||||
import java.awt.Graphics2D;
|
||||
import javax.swing.JComponent;
|
||||
|
||||
/**
|
||||
* @author Sergey.Malenkov
|
||||
*/
|
||||
final class DefaultScrollBarUI extends AbstractScrollBarUI {
|
||||
private static final JBColor THUMB_BACKGROUND = new JBColor(0x808080, 0x808080);
|
||||
private static final JBColor THUMB_FOREGROUND = new JBColor(0x6E6E6E, 0x949494);
|
||||
|
||||
private float myTrackValue;
|
||||
private float myThumbValue;
|
||||
|
||||
@Override
|
||||
int getThickness() {
|
||||
return scale(14);
|
||||
}
|
||||
|
||||
@Override
|
||||
int getMinimalThickness() {
|
||||
return scale(10);
|
||||
}
|
||||
|
||||
@Override
|
||||
void onTrackHover(boolean hover) {
|
||||
if (hover) {
|
||||
myTrackAnimator.startForward();
|
||||
}
|
||||
else {
|
||||
myTrackAnimator.startBackward();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void onThumbHover(boolean hover) {
|
||||
if (hover) {
|
||||
myThumbAnimator.startForward();
|
||||
}
|
||||
else {
|
||||
myThumbAnimator.startBackward();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void paintTrack(Graphics2D g, int x, int y, int width, int height, JComponent c) {
|
||||
Composite old = g.getComposite();
|
||||
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .1f * myTrackValue));
|
||||
g.setColor(Gray.x80);
|
||||
g.fillRect(x, y, width, height);
|
||||
g.setComposite(old);
|
||||
}
|
||||
|
||||
@Override
|
||||
void paintThumb(Graphics2D g, int x, int y, int width, int height, JComponent c) {
|
||||
Composite old = g.getComposite();
|
||||
g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .4f + .1f * myThumbValue));
|
||||
if (!c.isOpaque()) {
|
||||
Alignment alignment = Alignment.get(c);
|
||||
if (alignment == Alignment.LEFT || alignment == Alignment.RIGHT) {
|
||||
int offset = width - getMinimalThickness();
|
||||
if (offset > 0) {
|
||||
offset *= 1 - myThumbValue;
|
||||
width -= offset;
|
||||
if (alignment == Alignment.RIGHT) x += offset;
|
||||
}
|
||||
}
|
||||
else {
|
||||
int offset = height - getMinimalThickness();
|
||||
if (offset > 0) {
|
||||
offset *= 1 - myThumbValue;
|
||||
height -= offset;
|
||||
if (alignment == Alignment.BOTTOM) y += offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
g.setColor(THUMB_BACKGROUND);
|
||||
g.fillRect(x + 1, y + 1, width - 2, height - 2);
|
||||
g.setColor(THUMB_FOREGROUND);
|
||||
g.drawRect(x, y, width - 1, height - 1);
|
||||
g.setComposite(old);
|
||||
}
|
||||
|
||||
private TwoWayAnimator myTrackAnimator = new TwoWayAnimator("ScrollBarTrack", 6, 300, 300, 1000) {
|
||||
@Override
|
||||
void onFrame(int frame, int maxFrame) {
|
||||
myTrackValue = (float)frame / maxFrame;
|
||||
setTrackVisible(frame > 0);
|
||||
repaint();
|
||||
}
|
||||
};
|
||||
|
||||
private TwoWayAnimator myThumbAnimator = new TwoWayAnimator("ScrollBarThumb", 5, 125, 300, 1000) {
|
||||
@Override
|
||||
void onFrame(int frame, int maxFrame) {
|
||||
myThumbValue = (float)frame / maxFrame;
|
||||
repaint();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -15,15 +15,20 @@
|
||||
*/
|
||||
package com.intellij.ui.components;
|
||||
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.wm.IdeGlassPane;
|
||||
import com.intellij.ui.IdeBorderFactory;
|
||||
import com.intellij.ui.components.JBScrollBar.Alignment;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ReflectionUtil;
|
||||
import com.intellij.util.ui.ButtonlessScrollBarUI;
|
||||
import com.intellij.util.ui.JBInsets;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.border.LineBorder;
|
||||
import javax.swing.plaf.ScrollBarUI;
|
||||
import javax.swing.plaf.ScrollPaneUI;
|
||||
@@ -67,7 +72,7 @@ public class JBScrollPane extends JScrollPane {
|
||||
Container vp = c.getParent();
|
||||
if (vp instanceof JViewport) c = vp;
|
||||
}
|
||||
|
||||
|
||||
c = c.getParent();
|
||||
if (!(c instanceof JScrollPane)) return null;
|
||||
|
||||
@@ -77,10 +82,10 @@ public class JBScrollPane extends JScrollPane {
|
||||
private void init() {
|
||||
init(true);
|
||||
}
|
||||
|
||||
|
||||
private void init(boolean setupCorners) {
|
||||
setLayout(new ScrollPaneLayout());
|
||||
|
||||
setLayout(Registry.is("ide.scroll.new.layout") ? new Layout() : new ScrollPaneLayout());
|
||||
|
||||
if (setupCorners) {
|
||||
setupCorners();
|
||||
}
|
||||
@@ -102,9 +107,21 @@ public class JBScrollPane extends JScrollPane {
|
||||
|
||||
@Override
|
||||
public boolean isOptimizedDrawingEnabled() {
|
||||
if (getLayout() instanceof Layout) {
|
||||
return isOptimizedDrawingEnabledFor(getVerticalScrollBar()) &&
|
||||
isOptimizedDrawingEnabledFor(getHorizontalScrollBar());
|
||||
}
|
||||
return !myHasOverlayScrollbars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code false} for visible translucent scroll bars, or {@code true} otherwise.
|
||||
* It is needed to repaint translucent scroll bars on viewport repainting.
|
||||
*/
|
||||
private static boolean isOptimizedDrawingEnabledFor(JScrollBar bar) {
|
||||
return bar == null || bar.isOpaque() || !bar.isVisible();
|
||||
}
|
||||
|
||||
private void updateViewportBorder() {
|
||||
setViewportBorder(new ViewportBorder(myViewportBorderWidth >= 0 ? myViewportBorderWidth : 1));
|
||||
}
|
||||
@@ -138,8 +155,10 @@ public class JBScrollPane extends JScrollPane {
|
||||
// Now we let JScrollPane layout everything as necessary
|
||||
super.layout();
|
||||
|
||||
if (layout instanceof Layout) return;
|
||||
|
||||
if (scrollLayout != null) {
|
||||
// Now it's time to jump in and expand the viewport so it fits the whole area
|
||||
// Now it's time to jump in and expand the viewport so it fits the whole area
|
||||
// (taking into consideration corners, headers and other stuff).
|
||||
myHasOverlayScrollbars = relayoutScrollbars(
|
||||
this, scrollLayout,
|
||||
@@ -154,7 +173,7 @@ public class JBScrollPane extends JScrollPane {
|
||||
private boolean relayoutScrollbars(@NotNull JComponent container, @NotNull ScrollPaneLayout layout, boolean forceRelayout) {
|
||||
JViewport viewport = layout.getViewport();
|
||||
if (viewport == null) return false;
|
||||
|
||||
|
||||
JScrollBar vsb = layout.getVerticalScrollBar();
|
||||
JScrollBar hsb = layout.getHorizontalScrollBar();
|
||||
JViewport colHead = layout.getColumnHeader();
|
||||
@@ -225,7 +244,7 @@ public class JBScrollPane extends JScrollPane {
|
||||
|
||||
protected boolean isOverlaidScrollbar(@Nullable JScrollBar scrollbar) {
|
||||
if (!ButtonlessScrollBarUI.isMacOverlayScrollbarSupported()) return false;
|
||||
|
||||
|
||||
ScrollBarUI vsbUI = scrollbar == null ? null : scrollbar.getUI();
|
||||
return vsbUI instanceof ButtonlessScrollBarUI && !((ButtonlessScrollBarUI)vsbUI).alwaysShowTrack();
|
||||
}
|
||||
@@ -242,7 +261,9 @@ public class JBScrollPane extends JScrollPane {
|
||||
|
||||
@Override
|
||||
public void updateUI() {
|
||||
setUI(ButtonlessScrollBarUI.createNormal());
|
||||
setUI(!SystemInfo.isMac && Registry.is("ide.scroll.new.layout")
|
||||
? new DefaultScrollBarUI()
|
||||
: ButtonlessScrollBarUI.createNormal());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -327,4 +348,303 @@ public class JBScrollPane extends JScrollPane {
|
||||
lineColor = view.getBackground();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* These client properties modify a scroll pane layout.
|
||||
* Use the class object as a property key.
|
||||
*
|
||||
* @see #putClientProperty(Object, Object)
|
||||
*/
|
||||
public enum Flip {
|
||||
NONE, VERTICAL, HORIZONTAL, BOTH
|
||||
}
|
||||
|
||||
/**
|
||||
* ScrollPaneLayout implementation that supports
|
||||
* ScrollBar flipping and non-opaque ScrollBars.
|
||||
*/
|
||||
private static class Layout extends ScrollPaneLayout {
|
||||
private static final Insets EMPTY_INSETS = new Insets(0, 0, 0, 0);
|
||||
|
||||
@Override
|
||||
public void layoutContainer(Container parent) {
|
||||
JScrollPane pane = (JScrollPane)parent;
|
||||
// Calculate inner bounds of the scroll pane
|
||||
Rectangle bounds = new Rectangle(pane.getWidth(), pane.getHeight());
|
||||
JBInsets.removeFrom(bounds, pane.getInsets());
|
||||
// Determine positions of scroll bars on the scroll pane
|
||||
Object property = pane.getClientProperty(Flip.class);
|
||||
Flip flip = property instanceof Flip ? (Flip)property : Flip.NONE;
|
||||
boolean hsbOnTop = flip == Flip.BOTH || flip == Flip.VERTICAL;
|
||||
boolean vsbOnLeft = pane.getComponentOrientation().isLeftToRight()
|
||||
? flip == Flip.BOTH || flip == Flip.HORIZONTAL
|
||||
: flip == Flip.NONE || flip == Flip.VERTICAL;
|
||||
// If there's a visible row header remove the space it needs.
|
||||
// The row header is treated as if it were fixed width, arbitrary height.
|
||||
Rectangle rowHeadBounds = new Rectangle(bounds.x, 0, 0, 0);
|
||||
if (rowHead != null && rowHead.isVisible()) {
|
||||
rowHeadBounds.width = min(bounds.width, rowHead.getPreferredSize().width);
|
||||
bounds.width -= rowHeadBounds.width;
|
||||
if (vsbOnLeft) {
|
||||
rowHeadBounds.x += bounds.width;
|
||||
}
|
||||
else {
|
||||
bounds.x += rowHeadBounds.width;
|
||||
}
|
||||
}
|
||||
// If there's a visible column header remove the space it needs.
|
||||
// The column header is treated as if it were fixed height, arbitrary width.
|
||||
Rectangle colHeadBounds = new Rectangle(0, bounds.y, 0, 0);
|
||||
if (colHead != null && colHead.isVisible()) {
|
||||
colHeadBounds.height = min(bounds.height, colHead.getPreferredSize().height);
|
||||
bounds.height -= colHeadBounds.height;
|
||||
if (hsbOnTop) {
|
||||
colHeadBounds.y += bounds.height;
|
||||
}
|
||||
else {
|
||||
bounds.y += colHeadBounds.height;
|
||||
}
|
||||
}
|
||||
// If there's a JScrollPane.viewportBorder, remove the space it occupies
|
||||
Border border = pane.getViewportBorder();
|
||||
Insets insets = border == null ? null : border.getBorderInsets(parent);
|
||||
JBInsets.removeFrom(bounds, insets);
|
||||
if (insets == null) insets = EMPTY_INSETS;
|
||||
// At this point:
|
||||
// colHeadBounds is correct except for its width and x
|
||||
// rowHeadBounds is correct except for its height and y
|
||||
// bounds - the space available for the viewport and scroll bars
|
||||
// Once we're through computing the dimensions of these three parts
|
||||
// we can go back and set the bounds for the corners and the dimensions of
|
||||
// colHeadBounds.x, colHeadBounds.width, rowHeadBounds.y, rowHeadBounds.height.
|
||||
boolean isEmpty = bounds.width < 0 || bounds.height < 0;
|
||||
Component view = viewport == null ? null : viewport.getView();
|
||||
Dimension viewPreferredSize = view == null ? new Dimension() : view.getPreferredSize();
|
||||
Dimension viewportExtentSize = viewport == null ? new Dimension() : viewport.toViewCoordinates(bounds.getSize());
|
||||
// If the view is tracking the viewports width we don't bother with a horizontal scrollbar.
|
||||
// If the view is tracking the viewports height we don't bother with a vertical scrollbar.
|
||||
Scrollable scrollable = null;
|
||||
boolean viewTracksViewportWidth = false;
|
||||
boolean viewTracksViewportHeight = false;
|
||||
// Don't bother checking the Scrollable methods if there is no room for the viewport,
|
||||
// we aren't going to show any scroll bars in this case anyway.
|
||||
if (!isEmpty && view instanceof Scrollable) {
|
||||
scrollable = (Scrollable)view;
|
||||
viewTracksViewportWidth = scrollable.getScrollableTracksViewportWidth();
|
||||
viewTracksViewportHeight = scrollable.getScrollableTracksViewportHeight();
|
||||
}
|
||||
// If there's a vertical scroll bar and we need one, allocate space for it.
|
||||
// A vertical scroll bar is considered to be fixed width, arbitrary height.
|
||||
boolean vsbOpaque = false;
|
||||
boolean vsbNeeded = false;
|
||||
int vsbPolicy = pane.getVerticalScrollBarPolicy();
|
||||
if (!isEmpty && vsbPolicy != VERTICAL_SCROLLBAR_NEVER) {
|
||||
vsbNeeded = vsbPolicy == VERTICAL_SCROLLBAR_ALWAYS
|
||||
|| !viewTracksViewportHeight && viewPreferredSize.height > viewportExtentSize.height;
|
||||
}
|
||||
Rectangle vsbBounds = new Rectangle(0, bounds.y - insets.top, 0, 0);
|
||||
if (vsb != null) {
|
||||
vsbOpaque = vsb.isOpaque();
|
||||
if (vsbNeeded) {
|
||||
adjustForVSB(bounds, insets, vsbBounds, vsbOpaque, vsbOnLeft);
|
||||
if (vsbOpaque && viewport != null) {
|
||||
viewportExtentSize = viewport.toViewCoordinates(bounds.getSize());
|
||||
}
|
||||
}
|
||||
}
|
||||
// If there's a horizontal scroll bar and we need one, allocate space for it.
|
||||
// A horizontal scroll bar is considered to be fixed height, arbitrary width.
|
||||
boolean hsbOpaque = false;
|
||||
boolean hsbNeeded = false;
|
||||
int hsbPolicy = pane.getHorizontalScrollBarPolicy();
|
||||
if (!isEmpty && hsbPolicy != HORIZONTAL_SCROLLBAR_NEVER) {
|
||||
hsbNeeded = hsbPolicy == HORIZONTAL_SCROLLBAR_ALWAYS
|
||||
|| !viewTracksViewportWidth && viewPreferredSize.width > viewportExtentSize.width;
|
||||
}
|
||||
Rectangle hsbBounds = new Rectangle(bounds.x - insets.left, 0, 0, 0);
|
||||
if (hsb != null) {
|
||||
hsbOpaque = hsb.isOpaque();
|
||||
if (hsbNeeded) {
|
||||
adjustForHSB(bounds, insets, hsbBounds, hsbOpaque, hsbOnTop);
|
||||
if (hsbOpaque && viewport != null) {
|
||||
// If we added the horizontal scrollbar and reduced the vertical space
|
||||
// we may have to add the vertical scrollbar, if that hasn't been done so already.
|
||||
if (vsb != null && !vsbNeeded && vsbPolicy != VERTICAL_SCROLLBAR_NEVER) {
|
||||
viewportExtentSize = viewport.toViewCoordinates(bounds.getSize());
|
||||
vsbNeeded = viewPreferredSize.height > viewportExtentSize.height;
|
||||
if (vsbNeeded) adjustForVSB(bounds, insets, vsbBounds, vsbOpaque, vsbOnLeft);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Set the size of the viewport first, and then recheck the Scrollable methods.
|
||||
// Some components base their return values for the Scrollable methods on the size of the viewport,
|
||||
// so that if we don't ask after resetting the bounds we may have gotten the wrong answer.
|
||||
if (viewport != null) {
|
||||
viewport.setBounds(bounds);
|
||||
pane.setComponentZOrder(viewport, pane.getComponentCount() - 1);
|
||||
if (scrollable != null && hsbOpaque && vsbOpaque) {
|
||||
viewTracksViewportWidth = scrollable.getScrollableTracksViewportWidth();
|
||||
viewTracksViewportHeight = scrollable.getScrollableTracksViewportHeight();
|
||||
viewportExtentSize = viewport.toViewCoordinates(bounds.getSize());
|
||||
|
||||
boolean vsbNeededOld = vsbNeeded;
|
||||
if (vsb != null && vsbPolicy == VERTICAL_SCROLLBAR_AS_NEEDED) {
|
||||
boolean vsbNeededNew = !viewTracksViewportHeight && viewPreferredSize.height > viewportExtentSize.height;
|
||||
if (vsbNeeded != vsbNeededNew) {
|
||||
vsbNeeded = vsbNeededNew;
|
||||
if (vsbNeeded) {
|
||||
adjustForVSB(bounds, insets, vsbBounds, vsbOpaque, vsbOnLeft);
|
||||
}
|
||||
else if (vsbOpaque) {
|
||||
bounds.width += vsbBounds.width;
|
||||
}
|
||||
if (vsbOpaque) viewportExtentSize = viewport.toViewCoordinates(bounds.getSize());
|
||||
}
|
||||
}
|
||||
boolean hsbNeededOld = hsbNeeded;
|
||||
if (hsb != null && hsbPolicy == HORIZONTAL_SCROLLBAR_AS_NEEDED) {
|
||||
boolean hsbNeededNew = !viewTracksViewportWidth && viewPreferredSize.width > viewportExtentSize.width;
|
||||
if (hsbNeeded != hsbNeededNew) {
|
||||
hsbNeeded = hsbNeededNew;
|
||||
if (hsbNeeded) {
|
||||
adjustForHSB(bounds, insets, hsbBounds, hsbOpaque, hsbOnTop);
|
||||
}
|
||||
else if (hsbOpaque) {
|
||||
bounds.height += hsbBounds.height;
|
||||
}
|
||||
if (hsbOpaque && vsb != null && !vsbNeeded && vsbPolicy != VERTICAL_SCROLLBAR_NEVER) {
|
||||
viewportExtentSize = viewport.toViewCoordinates(bounds.getSize());
|
||||
vsbNeeded = viewPreferredSize.height > viewportExtentSize.height;
|
||||
if (vsbNeeded) adjustForVSB(bounds, insets, vsbBounds, vsbOpaque, vsbOnLeft);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hsbNeededOld != hsbNeeded || vsbNeededOld != vsbNeeded) {
|
||||
viewport.setBounds(bounds);
|
||||
// You could argue that we should recheck the Scrollable methods again until they stop changing,
|
||||
// but they might never stop changing, so we stop here and don't do any additional checks.
|
||||
}
|
||||
}
|
||||
}
|
||||
// Set the bounds of the row header.
|
||||
rowHeadBounds.y = bounds.y - insets.top;
|
||||
rowHeadBounds.height = bounds.height + insets.top + insets.bottom;
|
||||
if (rowHead != null) {
|
||||
rowHead.setBounds(rowHeadBounds);
|
||||
rowHead.putClientProperty(Alignment.class, vsbOnLeft ? Alignment.RIGHT : Alignment.LEFT);
|
||||
}
|
||||
// Set the bounds of the column header.
|
||||
colHeadBounds.x = bounds.x - insets.left;
|
||||
colHeadBounds.width = bounds.width + insets.left + insets.right;
|
||||
if (colHead != null) {
|
||||
colHead.setBounds(colHeadBounds);
|
||||
colHead.putClientProperty(Alignment.class, hsbOnTop ? Alignment.BOTTOM : Alignment.TOP);
|
||||
}
|
||||
// Set the bounds of the vertical scroll bar.
|
||||
vsbBounds.y = bounds.y - insets.top;
|
||||
vsbBounds.height = bounds.height + insets.top + insets.bottom;
|
||||
if (vsb != null) {
|
||||
vsb.setVisible(vsbNeeded);
|
||||
if (vsbNeeded) {
|
||||
if (vsbOpaque && colHead != null && UIManager.getBoolean("ScrollPane.fillUpperCorner")) {
|
||||
if ((vsbOnLeft ? upperLeft : upperRight) == null) {
|
||||
// This is used primarily for GTK L&F, which needs to extend
|
||||
// the vertical scrollbar to fill the upper corner near the column header.
|
||||
// Note that we skip this step (and use the default behavior)
|
||||
// if the user has set a custom corner component.
|
||||
if (!hsbOnTop) vsbBounds.y -= colHeadBounds.height;
|
||||
vsbBounds.height += colHeadBounds.height;
|
||||
}
|
||||
}
|
||||
vsb.setBounds(vsbBounds);
|
||||
vsb.putClientProperty(Alignment.class, vsbOnLeft ? Alignment.LEFT : Alignment.RIGHT);
|
||||
pane.setComponentZOrder(vsb, 0);
|
||||
}
|
||||
// Modify the bounds of the translucent scroll bar.
|
||||
if (!vsbOpaque) {
|
||||
if (!vsbOnLeft) vsbBounds.x += vsbBounds.width;
|
||||
vsbBounds.width = 0;
|
||||
}
|
||||
}
|
||||
// Set the bounds of the horizontal scroll bar.
|
||||
hsbBounds.x = bounds.x - insets.left;
|
||||
hsbBounds.width = bounds.width + insets.left + insets.right;
|
||||
if (hsb != null) {
|
||||
hsb.setVisible(hsbNeeded);
|
||||
if (hsbNeeded) {
|
||||
if (hsbOpaque && rowHead != null && UIManager.getBoolean("ScrollPane.fillLowerCorner")) {
|
||||
if ((vsbOnLeft ? lowerRight : lowerLeft) == null) {
|
||||
// This is used primarily for GTK L&F, which needs to extend
|
||||
// the horizontal scrollbar to fill the lower corner near the row header.
|
||||
// Note that we skip this step (and use the default behavior)
|
||||
// if the user has set a custom corner component.
|
||||
if (!vsbOnLeft) hsbBounds.x -= rowHeadBounds.width;
|
||||
hsbBounds.width += rowHeadBounds.width;
|
||||
}
|
||||
}
|
||||
hsb.setBounds(hsbBounds);
|
||||
hsb.putClientProperty(Alignment.class, hsbOnTop ? Alignment.TOP : Alignment.BOTTOM);
|
||||
}
|
||||
// Modify the bounds of the translucent scroll bar.
|
||||
if (!hsbOpaque) {
|
||||
if (!hsbOnTop) hsbBounds.y += hsbBounds.height;
|
||||
hsbBounds.height = 0;
|
||||
}
|
||||
}
|
||||
// Set the bounds of the corners.
|
||||
if (lowerLeft != null) {
|
||||
lowerLeft.setBounds(vsbOnLeft ? vsbBounds.x : rowHeadBounds.x,
|
||||
hsbOnTop ? colHeadBounds.y : hsbBounds.y,
|
||||
vsbOnLeft ? vsbBounds.width : rowHeadBounds.width,
|
||||
hsbOnTop ? colHeadBounds.height : hsbBounds.height);
|
||||
}
|
||||
if (lowerRight != null) {
|
||||
lowerRight.setBounds(vsbOnLeft ? rowHeadBounds.x : vsbBounds.x,
|
||||
hsbOnTop ? colHeadBounds.y : hsbBounds.y,
|
||||
vsbOnLeft ? rowHeadBounds.width : vsbBounds.width,
|
||||
hsbOnTop ? colHeadBounds.height : hsbBounds.height);
|
||||
}
|
||||
if (upperLeft != null) {
|
||||
upperLeft.setBounds(vsbOnLeft ? vsbBounds.x : rowHeadBounds.x,
|
||||
hsbOnTop ? hsbBounds.y : colHeadBounds.y,
|
||||
vsbOnLeft ? vsbBounds.width : rowHeadBounds.width,
|
||||
hsbOnTop ? hsbBounds.height : colHeadBounds.height);
|
||||
}
|
||||
if (upperRight != null) {
|
||||
upperRight.setBounds(vsbOnLeft ? rowHeadBounds.x : vsbBounds.x,
|
||||
hsbOnTop ? hsbBounds.y : colHeadBounds.y,
|
||||
vsbOnLeft ? rowHeadBounds.width : vsbBounds.width,
|
||||
hsbOnTop ? hsbBounds.height : colHeadBounds.height);
|
||||
}
|
||||
}
|
||||
|
||||
private void adjustForVSB(Rectangle bounds, Insets insets, Rectangle vsbBounds, boolean vsbOpaque, boolean vsbOnLeft) {
|
||||
vsbBounds.width = min(bounds.width, vsb.getPreferredSize().width);
|
||||
if (vsbOnLeft) {
|
||||
vsbBounds.x = bounds.x - insets.left/* + vsbBounds.width*/;
|
||||
if (vsbOpaque) bounds.x += vsbBounds.width;
|
||||
}
|
||||
else {
|
||||
vsbBounds.x = bounds.x + bounds.width + insets.right - vsbBounds.width;
|
||||
}
|
||||
if (vsbOpaque) bounds.width -= vsbBounds.width;
|
||||
}
|
||||
|
||||
private void adjustForHSB(Rectangle bounds, Insets insets, Rectangle hsbBounds, boolean hsbOpaque, boolean hsbOnTop) {
|
||||
hsbBounds.height = min(bounds.height, hsb.getPreferredSize().height);
|
||||
if (hsbOnTop) {
|
||||
hsbBounds.y = bounds.y - insets.top/* + hsbBounds.height*/;
|
||||
if (hsbOpaque) bounds.y += hsbBounds.height;
|
||||
}
|
||||
else {
|
||||
hsbBounds.y = bounds.y + bounds.height + insets.bottom - hsbBounds.height;
|
||||
}
|
||||
if (hsbOpaque) bounds.height -= hsbBounds.height;
|
||||
}
|
||||
|
||||
private static int min(int one, int two) {
|
||||
return Math.max(0, Math.min(one, two));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.ui.components;
|
||||
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.ui.Animator;
|
||||
|
||||
/**
|
||||
* @author Sergey.Malenkov
|
||||
*/
|
||||
abstract class TwoWayAnimator {
|
||||
private final Alarm myAlarm = new Alarm();
|
||||
private final MyAnimator myForwardAnimator;
|
||||
private final MyAnimator myBackwardAnimator;
|
||||
|
||||
private final int myMaxFrame;
|
||||
private int myFrame;
|
||||
|
||||
abstract void onFrame(int frame, int maxFrame);
|
||||
|
||||
TwoWayAnimator(String name, int totalFrames, int cycleDuration, int pauseForward, int pauseBackward) {
|
||||
myMaxFrame = totalFrames - 1;
|
||||
myForwardAnimator = new MyAnimator(name + "ForwardAnimator", totalFrames, cycleDuration, pauseForward, true);
|
||||
myBackwardAnimator = new MyAnimator(name + "BackwardAnimator", totalFrames, cycleDuration, pauseBackward, false);
|
||||
}
|
||||
|
||||
void startForward() {
|
||||
stop();
|
||||
myForwardAnimator.start();
|
||||
}
|
||||
|
||||
void startBackward() {
|
||||
stop();
|
||||
myBackwardAnimator.start();
|
||||
}
|
||||
|
||||
private void stop() {
|
||||
myAlarm.cancelAllRequests();
|
||||
myForwardAnimator.suspend();
|
||||
myBackwardAnimator.suspend();
|
||||
}
|
||||
|
||||
private final class MyAnimator extends Animator implements Runnable {
|
||||
private final int myPause;
|
||||
|
||||
private MyAnimator(String name, int totalFrames, int cycleDuration, int pause, boolean forward) {
|
||||
super(name, totalFrames, cycleDuration, false, forward);
|
||||
myPause = pause;
|
||||
}
|
||||
|
||||
private void start() {
|
||||
if (isForward() ? myFrame > 0 : myFrame < myMaxFrame) {
|
||||
run();
|
||||
}
|
||||
else {
|
||||
myAlarm.addRequest(this, myPause);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
reset();
|
||||
resume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintNow(int frame, int totalFrames, int cycle) {
|
||||
if (isForward() ? (frame > myFrame) : (frame < myFrame)) {
|
||||
myFrame = frame;
|
||||
onFrame(myFrame, myMaxFrame);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
@@ -16,7 +16,6 @@
|
||||
package com.intellij.util;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.StandardFileSystems;
|
||||
import com.intellij.util.io.URLUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -71,7 +70,7 @@ public final class UrlImpl implements Url {
|
||||
|
||||
@Override
|
||||
public boolean isInLocalFileSystem() {
|
||||
return StandardFileSystems.FILE_PROTOCOL.equals(scheme);
|
||||
return URLUtil.FILE_PROTOCOL.equals(scheme);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -95,7 +95,7 @@ file.already.exist=File {0} already exists
|
||||
file.already.exist.title=Extract Include File
|
||||
name.for.extracted.include.file=&Name for extracted include file (default extension: {0})
|
||||
extract.to.directory=Extract to &directory:
|
||||
select.target.directory=Select target directory
|
||||
select.target.directory=Select Target Directory
|
||||
select.target.directory.description=The file will be created in this directory
|
||||
create.directory=Create directory
|
||||
replace.inheritance.from=&Replace with delegation inheritance from:
|
||||
|
||||
+1
-1
@@ -163,7 +163,7 @@ public class ProjectFileIndexImpl extends FileIndexBase implements ProjectFileIn
|
||||
|
||||
@Override
|
||||
public String getPackageNameByDirectory(@NotNull VirtualFile dir) {
|
||||
LOG.assertTrue(dir.isDirectory());
|
||||
LOG.assertTrue(dir.isDirectory(), dir.getPresentableUrl());
|
||||
return myDirectoryIndex.getPackageName(dir);
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -58,6 +58,7 @@ open class ApplicationRule : ExternalResource() {
|
||||
override public final fun before() {
|
||||
IdeaTestApplication.getInstance()
|
||||
TestRunnerUtil.replaceIdeEventQueueSafely()
|
||||
(PersistentFS.getInstance() as PersistentFSImpl).cleanPersistedContents()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.testFramework
|
||||
|
||||
import java.nio.file.FileSystem
|
||||
|
||||
fun FileSystem.file(path: String, data: ByteArray): FileSystem {
|
||||
getPath(path).write(data)
|
||||
return this
|
||||
}
|
||||
|
||||
fun FileSystem.file(path: String, data: String) = file(path, data.toByteArray())
|
||||
+15
@@ -1,3 +1,18 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.testFramework
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
@@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$/test-framework-java8">
|
||||
<sourceFolder url="file://$MODULE_DIR$/test-framework-java8/src" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/test-framework-java8" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="testFramework" />
|
||||
<orderEntry type="library" name="assertJ" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -1,10 +0,0 @@
|
||||
package com.intellij.testFramework
|
||||
|
||||
import java.nio.file.FileSystem
|
||||
|
||||
fun FileSystem.file(path: String, data: ByteArray): FileSystem {
|
||||
getPath(path).write(data)
|
||||
return this
|
||||
}
|
||||
|
||||
fun FileSystem.file(path: String, data: String) = file(path, data.toByteArray())
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module relativePaths="true" type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
@@ -25,5 +25,6 @@
|
||||
<orderEntry type="module" module-name="images" exported="" scope="RUNTIME" />
|
||||
<orderEntry type="module" module-name="RegExpSupport" exported="" scope="RUNTIME" />
|
||||
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
|
||||
<orderEntry type="library" name="assertJ" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -140,7 +140,10 @@ public class UsagePreviewPanel extends UsageContextPanelBase {
|
||||
|
||||
TextRange elementRange = psiElement.getTextRange();
|
||||
TextRange infoRange = info.getRangeInElement();
|
||||
TextRange textRange = infoRange == null || infoRange.getStartOffset() > elementRange.getLength() ? null : elementRange.cutOut(infoRange);
|
||||
TextRange textRange = infoRange == null
|
||||
|| infoRange.getStartOffset() > elementRange.getLength()
|
||||
|| infoRange.getEndOffset() > elementRange.getLength() ? null
|
||||
: elementRange.cutOut(infoRange);
|
||||
if (textRange == null) textRange = elementRange;
|
||||
// hack to determine element range to highlight
|
||||
if (psiElement instanceof PsiNamedElement && !(psiElement instanceof PsiFile)) {
|
||||
|
||||
@@ -50,11 +50,11 @@ public class PathUtilRt {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String suggestFileName(@NotNull String text, final boolean allowDots, final boolean allowSpaces) {
|
||||
public static String suggestFileName(@NotNull String text, boolean allowDots, boolean allowSpaces) {
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (int i = 0; i < text.length(); i++) {
|
||||
char c = text.charAt(i);
|
||||
if (!isValidFileNameChar(c) || (!allowDots && c == '.') || (!allowSpaces && Character.isWhitespace(c))) {
|
||||
if (!isValidFileNameChar(c, true) || (!allowDots && c == '.') || (!allowSpaces && Character.isWhitespace(c))) {
|
||||
result.append('_');
|
||||
}
|
||||
else {
|
||||
@@ -65,19 +65,24 @@ public class PathUtilRt {
|
||||
}
|
||||
|
||||
public static boolean isValidFileName(@NotNull String fileName) {
|
||||
return isValidFileName(fileName, true);
|
||||
}
|
||||
|
||||
public static boolean isValidFileName(@NotNull String fileName, boolean strict) {
|
||||
if (fileName.length() == 0 || fileName.equals(".") || fileName.equals("..")) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < fileName.length(); i++) {
|
||||
if (!isValidFileNameChar(fileName.charAt(i))) {
|
||||
if (!isValidFileNameChar(fileName.charAt(i), strict)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isValidFileNameChar(char c) {
|
||||
return c != '/' && c != '\\' && c != '\t' && c != '\n' && c != '\r' && c != ':' && c != ';' && c != '*' && c != '?' &&
|
||||
c != '"' && c != '\'' && c != '<' && c != '>';
|
||||
private static boolean isValidFileNameChar(char c, boolean strict) {
|
||||
if (c == '/' || c == '\\') return false;
|
||||
if (!strict) return true;
|
||||
return c != '\t' && c != '\n' && c != '\r' && c != ':' && c != ';' && c != '*' && c != '?' && c != '"' && c != '\'' && c != '<' && c != '>';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -110,6 +110,7 @@ ide.tree.deferred.icon.invalidates.cache=true
|
||||
|
||||
ide.splitter.mouseZone=6
|
||||
ide.smart.horizontal.scrolling=true
|
||||
ide.scroll.new.layout=false
|
||||
|
||||
ide.tooltip.callout=true
|
||||
ide.tooltip.animationCycle=150
|
||||
|
||||
@@ -168,7 +168,11 @@ public class UIUtil {
|
||||
if (isUnderAquaBasedLookAndFeel()) {
|
||||
c.putClientProperty("JComponent.sizeVariant", StringUtil.toLowerCase(componentStyle.name()));
|
||||
}
|
||||
FontSize fontSize = componentStyle == ComponentStyle.REGULAR ? FontSize.NORMAL : componentStyle == ComponentStyle.SMALL ? FontSize.SMALL : FontSize.MINI;
|
||||
FontSize fontSize = componentStyle == ComponentStyle.MINI
|
||||
? FontSize.MINI
|
||||
: componentStyle == ComponentStyle.SMALL
|
||||
? FontSize.SMALL
|
||||
: FontSize.NORMAL;
|
||||
c.setFont(getFont(fontSize, c.getFont()));
|
||||
Container p = c.getParent();
|
||||
if (p != null) {
|
||||
@@ -210,7 +214,7 @@ public class UIUtil {
|
||||
|
||||
public enum FontSize {NORMAL, SMALL, MINI}
|
||||
|
||||
public enum ComponentStyle {REGULAR, SMALL, MINI}
|
||||
public enum ComponentStyle {LARGE, REGULAR, SMALL, MINI}
|
||||
|
||||
public enum FontColor {NORMAL, BRIGHTER}
|
||||
|
||||
@@ -1853,7 +1857,7 @@ public class UIUtil {
|
||||
//noinspection StatementWithEmptyBody
|
||||
while(dispatchInvocationEvent());
|
||||
}
|
||||
|
||||
|
||||
@TestOnly
|
||||
public static boolean dispatchInvocationEvent() {
|
||||
assert EdtInvocationManager.getInstance().isEventDispatchThread() : Thread.currentThread() + "; EDT: "+getEventQueueThread();
|
||||
@@ -1871,7 +1875,7 @@ public class UIUtil {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private static Thread getEventQueueThread() {
|
||||
EventQueue eventQueue = Toolkit.getDefaultToolkit().getSystemEventQueue();
|
||||
try {
|
||||
@@ -2128,7 +2132,7 @@ public class UIUtil {
|
||||
for (MouseWheelListener each : mouseWheelListeners) {
|
||||
c.removeMouseWheelListener(each);
|
||||
}
|
||||
|
||||
|
||||
if (c instanceof AbstractButton) {
|
||||
final ActionListener[] listeners = ((AbstractButton)c).getActionListeners();
|
||||
for (ActionListener listener : listeners) {
|
||||
@@ -2240,7 +2244,7 @@ public class UIUtil {
|
||||
public static HTMLEditorKit getHTMLEditorKit() {
|
||||
return getHTMLEditorKit(true);
|
||||
}
|
||||
|
||||
|
||||
public static HTMLEditorKit getHTMLEditorKit(boolean noGapsBetweenParagraphs) {
|
||||
Font font = getLabelFont();
|
||||
@NonNls String family = !SystemInfo.isWindows && font != null ? font.getFamily() : "Tahoma";
|
||||
@@ -2940,7 +2944,7 @@ public class UIUtil {
|
||||
g.drawString(text, xOffset, yOffset[0]);
|
||||
if (!StringUtil.isEmpty(shortcut)) {
|
||||
Color oldColor = g.getColor();
|
||||
g.setColor(new JBColor(new Color(82, 99, 155),
|
||||
g.setColor(new JBColor(new Color(82, 99, 155),
|
||||
new Color(88, 157, 246)));
|
||||
g.drawString(shortcut, xOffset + fm.stringWidth(text + (isUnderDarcula() ? " " : "")), yOffset[0]);
|
||||
g.setColor(oldColor);
|
||||
@@ -3063,9 +3067,9 @@ public class UIUtil {
|
||||
public static void setNotOpaqueRecursively(@NotNull Component component) {
|
||||
if (!isUnderAquaLookAndFeel()) return;
|
||||
|
||||
if (component.getBackground().equals(getPanelBackground())
|
||||
|| component instanceof JScrollPane
|
||||
|| component instanceof JViewport
|
||||
if (component.getBackground().equals(getPanelBackground())
|
||||
|| component instanceof JScrollPane
|
||||
|| component instanceof JViewport
|
||||
|| component instanceof JLayeredPane) {
|
||||
if (component instanceof JComponent) {
|
||||
((JComponent)component).setOpaque(false);
|
||||
@@ -3550,4 +3554,21 @@ public class UIUtil {
|
||||
Component component = policy.getFirstComponent(container);
|
||||
return component instanceof JComponent ? (JComponent)component : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates a component style from the corresponding client property.
|
||||
* The key "JComponent.sizeVariant" is used by Apple's L&F to scale components.
|
||||
*
|
||||
* @param component a component to process
|
||||
* @return a component style of the specified component
|
||||
*/
|
||||
public static ComponentStyle getComponentStyle(Component component) {
|
||||
if (component instanceof JComponent) {
|
||||
Object property = ((JComponent)component).getClientProperty("JComponent.sizeVariant");
|
||||
if ("large".equals(property)) return ComponentStyle.LARGE;
|
||||
if ("small".equals(property)) return ComponentStyle.SMALL;
|
||||
if ("mini".equals(property)) return ComponentStyle.MINI;
|
||||
}
|
||||
return ComponentStyle.REGULAR;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.util;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class PathUtilTest {
|
||||
@Test
|
||||
public void isValidFileName() throws Exception {
|
||||
assertFalse(PathUtilRt.isValidFileName("", false));
|
||||
assertFalse(PathUtilRt.isValidFileName(".", false));
|
||||
assertFalse(PathUtilRt.isValidFileName("..", false));
|
||||
assertFalse(PathUtilRt.isValidFileName("a/b", false));
|
||||
assertFalse(PathUtilRt.isValidFileName("a\\b", false));
|
||||
|
||||
assertFalse(PathUtilRt.isValidFileName("a:b"));
|
||||
assertTrue(PathUtilRt.isValidFileName("a:b", false));
|
||||
}
|
||||
}
|
||||
+6
-5
@@ -303,10 +303,10 @@
|
||||
bundle="com.siyeh.InspectionGadgetsBundle" key="non.short.circuit.boolean.expression.display.name"
|
||||
groupBundle="messages.InspectionsBundle" groupKey="group.names.probable.bugs" enabledByDefault="false" level="WARNING"
|
||||
implementationClass="com.siyeh.ig.bugs.NonShortCircuitBooleanInspection"/>
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="NullArgumentToVariableArgMethod" bundle="com.siyeh.InspectionGadgetsBundle"
|
||||
key="null.argument.to.var.arg.method.display.name" groupBundle="messages.InspectionsBundle"
|
||||
groupKey="group.names.probable.bugs" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="com.siyeh.ig.bugs.NullArgumentToVariableArgMethodInspection"/>
|
||||
<localInspection groupPath="Java" language="JAVA" suppressId="ConfusingArgumentToVarargsMethod" alternativeId="NullArgumentToVariableArgMethod"
|
||||
shortName="NullArgumentToVariableArgMethod" bundle="com.siyeh.InspectionGadgetsBundle"
|
||||
key="null.argument.to.var.arg.method.display.name" groupBundle="messages.InspectionsBundle" groupKey="group.names.probable.bugs"
|
||||
enabledByDefault="true" level="WARNING" implementationClass="com.siyeh.ig.bugs.NullArgumentToVariableArgMethodInspection"/>
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="NumberEquality" bundle="com.siyeh.InspectionGadgetsBundle" key="number.comparison.display.name"
|
||||
groupBundle="messages.InspectionsBundle" groupKey="group.names.probable.bugs" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="com.siyeh.ig.bugs.NumberEqualityInspection"/>
|
||||
@@ -319,7 +319,8 @@
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="ObjectToString" bundle="com.siyeh.InspectionGadgetsBundle" key="default.tostring.call.display.name"
|
||||
groupBundle="messages.InspectionsBundle" groupKey="group.names.probable.bugs" enabledByDefault="false" level="WARNING"
|
||||
implementationClass="com.siyeh.ig.bugs.ObjectToStringInspection"/>
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="PrimitiveArrayArgumentToVariableArgMethod" bundle="com.siyeh.InspectionGadgetsBundle"
|
||||
<localInspection groupPath="Java" language="JAVA" suppressId="PrimitiveArrayArgumentToVarargsMethod" alternativeId="PrimitiveArrayArgumentToVariableArgMethod"
|
||||
shortName="PrimitiveArrayArgumentToVariableArgMethod" bundle="com.siyeh.InspectionGadgetsBundle"
|
||||
key="primitive.array.argument.to.var.arg.method.display.name" groupBundle="messages.InspectionsBundle"
|
||||
groupKey="group.names.probable.bugs" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="com.siyeh.ig.bugs.PrimitiveArrayArgumentToVariableArgMethodInspection"/>
|
||||
|
||||
+6
-6
@@ -128,10 +128,10 @@ misspelled.tostring.problem.descriptor=<code>#ref()</code> method should probabl
|
||||
non.short.circuit.boolean.expression.display.name=Non-short-circuit boolean expression
|
||||
non.short.circuit.boolean.expression.problem.descriptor=Non-short-circuit boolean expression <code>#ref</code> #loc
|
||||
non.short.circuit.boolean.expression.replace.quickfix=Replace with short circuit expression
|
||||
null.argument.to.var.arg.method.display.name=Confusing 'null' argument to var-arg method
|
||||
null.argument.to.var.arg.method.problem.descriptor=Confusing <code>#ref</code> argument to var-arg method #loc
|
||||
primitive.array.argument.to.var.arg.method.display.name=Confusing primitive array argument to var-arg method
|
||||
primitive.array.argument.to.var.arg.method.problem.descriptor=Confusing primitive array argument to var-arg method #loc
|
||||
null.argument.to.var.arg.method.display.name=Confusing argument to varargs method
|
||||
null.argument.to.var.arg.method.problem.descriptor=Confusing argument <code>#ref</code>, unclear if a varargs or non-varargs call is desired #loc
|
||||
primitive.array.argument.to.var.arg.method.display.name=Confusing primitive array argument to varargs method
|
||||
primitive.array.argument.to.var.arg.method.problem.descriptor=Confusing primitive array argument to varargs method #loc
|
||||
object.comparison.display.name=Object comparison using '==', instead of 'equals()'
|
||||
object.comparison.enumerated.ignore.option=Ignore '==' between enumerated types
|
||||
object.comparison.klass.ignore.option=Ignore '==' on 'java.lang.Class' objects
|
||||
@@ -1874,8 +1874,8 @@ array.hash.code.display.name='hashCode()' called on array
|
||||
array.hash.code.problem.descriptor=<code>#ref()</code> called on array should probably be 'Arrays.hashCode()' #loc
|
||||
arrays.deep.hash.code.quickfix=Replace with 'Arrays.deepHashCode()'
|
||||
arrays.hash.code.quickfix=Replace with 'Arrays.hashCode()'
|
||||
method.can.be.variable.arity.method.display.name=Method can be variable arity method
|
||||
method.can.be.variable.arity.method.problem.descriptor=<code>#ref()</code> can be converted to variable arity method #loc
|
||||
method.can.be.variable.arity.method.display.name=Method can be varargs method
|
||||
method.can.be.variable.arity.method.problem.descriptor=<code>#ref()</code> can be converted to varargs method #loc
|
||||
method.can.be.variable.arity.method.ignore.byte.short.option=Ignore methods with a last parameter of type byte[] or short[]
|
||||
method.can.be.variable.arity.method.ignore.multiple.arrays.option=Ignore methods with multiple array parameters
|
||||
convert.to.variable.arity.method.quickfix=Convert to varargs method
|
||||
|
||||
+60
-21
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2014 Dave Griffith, Bas Leijdekkers
|
||||
* Copyright 2003-2015 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,29 +15,53 @@
|
||||
*/
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.AddTypeCastFix;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.psiutils.ExpressionUtils;
|
||||
import com.siyeh.ig.DelegatingFix;
|
||||
import com.siyeh.ig.InspectionGadgetsFix;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class NullArgumentToVariableArgMethodInspection
|
||||
extends BaseInspection {
|
||||
public class NullArgumentToVariableArgMethodInspection extends BaseInspection {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getID() {
|
||||
return "ConfusingArgumentToVarargsMethod";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getAlternativeID() {
|
||||
return "NullArgumentToVariableArgMethod"; // old suppressions should keep working
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getDisplayName() {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"null.argument.to.var.arg.method.display.name");
|
||||
return InspectionGadgetsBundle.message("null.argument.to.var.arg.method.display.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String buildErrorString(Object... infos) {
|
||||
return InspectionGadgetsBundle.message(
|
||||
"null.argument.to.var.arg.method.problem.descriptor");
|
||||
return InspectionGadgetsBundle.message("null.argument.to.var.arg.method.problem.descriptor");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected InspectionGadgetsFix[] buildFixes(Object... infos) {
|
||||
final PsiExpression argument = (PsiExpression)infos[0];
|
||||
final PsiType type1 = (PsiType)infos[1];
|
||||
final PsiType type2 = (PsiType)infos[2];
|
||||
return new InspectionGadgetsFix[] {
|
||||
new DelegatingFix(new AddTypeCastFix(type1, argument)),
|
||||
new DelegatingFix(new AddTypeCastFix(type2, argument))
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -55,21 +79,26 @@ public class NullArgumentToVariableArgMethodInspection
|
||||
return new NullArgumentToVariableArgVisitor();
|
||||
}
|
||||
|
||||
private static class NullArgumentToVariableArgVisitor
|
||||
extends BaseInspectionVisitor {
|
||||
private static class NullArgumentToVariableArgVisitor extends BaseInspectionVisitor {
|
||||
|
||||
@Override
|
||||
public void visitMethodCallExpression(
|
||||
@NotNull PsiMethodCallExpression call) {
|
||||
public void visitMethodCallExpression(@NotNull PsiMethodCallExpression call) {
|
||||
super.visitMethodCallExpression(call);
|
||||
|
||||
final PsiExpressionList argumentList = call.getArgumentList();
|
||||
final PsiExpression[] args = argumentList.getExpressions();
|
||||
if (args.length == 0) {
|
||||
final PsiExpression[] arguments = argumentList.getExpressions();
|
||||
if (arguments.length == 0) {
|
||||
return;
|
||||
}
|
||||
final PsiExpression lastArg = args[args.length - 1];
|
||||
if (!ExpressionUtils.isNullLiteral(lastArg)) {
|
||||
final PsiExpression lastArgument = arguments[arguments.length - 1];
|
||||
final PsiType type = lastArgument.getType();
|
||||
final boolean checkArray;
|
||||
if (PsiType.NULL.equals(type)) {
|
||||
checkArray = false;
|
||||
}
|
||||
else if (type instanceof PsiArrayType) {
|
||||
checkArray = true;
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
final PsiMethod method = call.resolveMethod();
|
||||
@@ -77,16 +106,26 @@ public class NullArgumentToVariableArgMethodInspection
|
||||
return;
|
||||
}
|
||||
final PsiParameterList parameterList = method.getParameterList();
|
||||
if (parameterList.getParametersCount() != args.length) {
|
||||
if (parameterList.getParametersCount() != arguments.length) {
|
||||
return;
|
||||
}
|
||||
final PsiParameter[] parameters = parameterList.getParameters();
|
||||
final PsiParameter lastParameter =
|
||||
parameters[parameters.length - 1];
|
||||
final PsiParameter lastParameter = parameters[parameters.length - 1];
|
||||
if (!lastParameter.isVarArgs()) {
|
||||
return;
|
||||
}
|
||||
registerError(lastArg);
|
||||
final PsiType type1 = lastParameter.getType();
|
||||
if (!(type1 instanceof PsiEllipsisType)) {
|
||||
return;
|
||||
}
|
||||
final PsiEllipsisType ellipsisType = (PsiEllipsisType)type1;
|
||||
final PsiType arrayType = ellipsisType.toArrayType();
|
||||
if (checkArray) {
|
||||
if (arrayType.equals(type) || !arrayType.isAssignableFrom(type)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
registerError(lastArgument, lastArgument, ellipsisType.getComponentType(), arrayType);
|
||||
}
|
||||
}
|
||||
}
|
||||
+27
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2006-2014 Dave Griffith, Bas Leijdekkers
|
||||
* Copyright 2006-2015 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,18 +16,34 @@
|
||||
package com.siyeh.ig.bugs;
|
||||
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.AddTypeCastFix;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.DelegatingFix;
|
||||
import com.siyeh.ig.InspectionGadgetsFix;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class PrimitiveArrayArgumentToVariableArgMethodInspection extends BaseInspection {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getID() {
|
||||
return "PrimitiveArrayArgumentToVarargsMethod";
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String getAlternativeID() {
|
||||
return "PrimitiveArrayArgumentToVariableArgMethod"; // keep old suppression working
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getDisplayName() {
|
||||
@@ -50,6 +66,14 @@ public class PrimitiveArrayArgumentToVariableArgMethodInspection extends BaseIns
|
||||
return PsiUtil.isLanguageLevel5OrHigher(file);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected InspectionGadgetsFix buildFix(Object... infos) {
|
||||
final PsiExpression argument = (PsiExpression)infos[0];
|
||||
final PsiType type = (PsiType)infos[1];
|
||||
return new DelegatingFix(new AddTypeCastFix(type, argument));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseInspectionVisitor buildVisitor() {
|
||||
return new PrimitiveArrayArgumentToVariableArgVisitor();
|
||||
@@ -84,11 +108,11 @@ public class PrimitiveArrayArgumentToVariableArgMethodInspection extends BaseIns
|
||||
if (!lastParameter.isVarArgs()) {
|
||||
return;
|
||||
}
|
||||
final PsiType parameterType = lastParameter.getType();
|
||||
final PsiEllipsisType parameterType = (PsiEllipsisType)lastParameter.getType();
|
||||
if (isDeepPrimitiveArrayType(parameterType, result.getSubstitutor())) {
|
||||
return;
|
||||
}
|
||||
registerError(lastArgument);
|
||||
registerError(lastArgument, lastArgument, parameterType.getComponentType());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
-12
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2003-2013 Dave Griffith, Bas Leijdekkers
|
||||
* Copyright 2003-2015 Dave Griffith, Bas Leijdekkers
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,12 +20,12 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.FileTypeUtils;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.siyeh.InspectionGadgetsBundle;
|
||||
import com.siyeh.ig.BaseInspection;
|
||||
import com.siyeh.ig.BaseInspectionVisitor;
|
||||
import com.siyeh.ig.InspectionGadgetsFix;
|
||||
import com.siyeh.ig.psiutils.ClassUtils;
|
||||
import com.siyeh.ig.psiutils.ExpressionUtils;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -98,8 +98,7 @@ public class PrivateMemberAccessBetweenOuterAndInnerClassInspection
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFix(Project project, ProblemDescriptor descriptor)
|
||||
throws IncorrectOperationException {
|
||||
public void doFix(Project project, ProblemDescriptor descriptor) {
|
||||
final PsiElement element = descriptor.getPsiElement();
|
||||
if (constructor) {
|
||||
makeConstructorPackageLocal(project, element);
|
||||
@@ -127,8 +126,7 @@ public class PrivateMemberAccessBetweenOuterAndInnerClassInspection
|
||||
modifiers.setModifierProperty(PsiModifier.PRIVATE, false);
|
||||
}
|
||||
|
||||
private static void makeConstructorPackageLocal(Project project,
|
||||
PsiElement element) {
|
||||
private static void makeConstructorPackageLocal(Project project, PsiElement element) {
|
||||
final PsiNewExpression newExpression =
|
||||
PsiTreeUtil.getParentOfType(element,
|
||||
PsiNewExpression.class);
|
||||
@@ -175,8 +173,7 @@ public class PrivateMemberAccessBetweenOuterAndInnerClassInspection
|
||||
return new PrivateMemberAccessFromInnerClassVisitor();
|
||||
}
|
||||
|
||||
private static class PrivateMemberAccessFromInnerClassVisitor
|
||||
extends BaseInspectionVisitor {
|
||||
private static class PrivateMemberAccessFromInnerClassVisitor extends BaseInspectionVisitor {
|
||||
|
||||
@Override
|
||||
public void visitNewExpression(PsiNewExpression expression) {
|
||||
@@ -219,11 +216,9 @@ public class PrivateMemberAccessBetweenOuterAndInnerClassInspection
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitReferenceExpression(
|
||||
@NotNull PsiReferenceExpression expression) {
|
||||
public void visitReferenceExpression(@NotNull PsiReferenceExpression expression) {
|
||||
super.visitReferenceExpression(expression);
|
||||
final PsiElement referenceNameElement =
|
||||
expression.getReferenceNameElement();
|
||||
final PsiElement referenceNameElement = expression.getReferenceNameElement();
|
||||
if (referenceNameElement == null) {
|
||||
return;
|
||||
}
|
||||
@@ -235,6 +230,10 @@ public class PrivateMemberAccessBetweenOuterAndInnerClassInspection
|
||||
if (!member.hasModifierProperty(PsiModifier.PRIVATE)) {
|
||||
return;
|
||||
}
|
||||
final Object value = ExpressionUtils.computeConstantExpression(expression);
|
||||
if (value != null) {
|
||||
return; // no synthetic accessor created, compile time constant will be inlined by javac
|
||||
}
|
||||
final PsiElement containingClass = getContainingContextClass(expression);
|
||||
if (containingClass == null) {
|
||||
return;
|
||||
|
||||
+3
-3
@@ -1,19 +1,19 @@
|
||||
<html>
|
||||
<body>
|
||||
Reports methods with which can be converted to be a variable
|
||||
arity/varargs method, available in Java 5 and newer.
|
||||
arity method, available in Java 5 and newer.
|
||||
<p>
|
||||
This inspection only reports if the project or module is configured to use a
|
||||
language level of 5.0 or higher.
|
||||
<!-- tooltip end -->
|
||||
<p>
|
||||
Use the first checkbox below to not offer to convert <b>byte[]</b> or <b>short[]</b> parameters to vararg.
|
||||
Use the first checkbox below to not offer to convert <b>byte[]</b> or <b>short[]</b> parameters to varargs.
|
||||
<p>
|
||||
Use the second checkbox below to ignore methods overriding or implementing a method from a superclass.
|
||||
<p>
|
||||
Use the third checkbox below to only report when the method is <b>public</b>
|
||||
<p>
|
||||
Use the fourth checkbox below ot ignore method with more than one array parameter.
|
||||
Use the fourth checkbox below to ignore methods with two or more array parameters.
|
||||
<p>
|
||||
</body>
|
||||
</html>
|
||||
+4
-4
@@ -1,9 +1,9 @@
|
||||
<html>
|
||||
<body>
|
||||
Reports any calls to a variable-argument method which has a <b>null</b>
|
||||
in the variable-argument position (e.g <b>System.out.printf("%s", null)</b> ).
|
||||
Such a <b>null</b> argument may be confusing, as it is not
|
||||
wrapped as a single-element array, as may be expected.
|
||||
Reports any calls to a variable arity method where the call has a single argument
|
||||
in the variable arity parameter position, which is either a <b>null</b> or an array of a subtype of the variable arity parameter.
|
||||
Such an argument may be confusing as it is unclear if a varargs or non-varargs call is desired.
|
||||
For example <code>System.out.printf("%s", null)</code>.
|
||||
<!-- tooltip end -->
|
||||
<p>
|
||||
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
<html>
|
||||
<body>
|
||||
Reports any calls to a variable-argument method which has a primitive array in
|
||||
in the variable-argument position (e.g <b>System.out.printf("%s", new int[]{1, 2, 3})</b> ).
|
||||
Reports any calls to a variable arity method where the call has a primitive array in
|
||||
in the variable arity parameter position (e.g <b>System.out.printf("%s", new int[]{1, 2, 3})</b> ).
|
||||
Such a primitive-array argument may be confusing, as it will wrapped as a single-element array, rather than each individual
|
||||
element being boxed, as might be expected.
|
||||
<!-- tooltip end -->
|
||||
|
||||
+3
@@ -3,6 +3,9 @@
|
||||
This inspection is intended for J2ME and other highly resource constrained environments.
|
||||
Applying the results of this inspection without consideration might have negative effects on code clarity and design.
|
||||
<p>
|
||||
Reports references to non-constant <b>private</b> members of an outer class from inside an inner class or
|
||||
to members of an inner class from a containing class.
|
||||
<p>
|
||||
An inner class and its containing class are compiled to separate
|
||||
class files. The virtual machine normally prohibits access from a class to private fields and methods of
|
||||
another class. To enable access from an inner class to private members of a
|
||||
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
<html>
|
||||
<body>
|
||||
Reports methods overriding a variable arity (varargs) method with an array parameter. While this is legal Java, it can be confusing.
|
||||
Reports methods overriding a variable arity method and replacing the variable arity parameter with an array parameter.
|
||||
While this is legal Java, it can be confusing.
|
||||
<!-- tooltip end -->
|
||||
<p>
|
||||
</body>
|
||||
|
||||
+3
-2
@@ -1,9 +1,10 @@
|
||||
package com.siyeh.igtest.bugs.null_argument_to_variable_arg_method;
|
||||
|
||||
public class NullArgumentToVariableArgMethod {
|
||||
public void foo()
|
||||
public void foo(String[] ss)
|
||||
{
|
||||
String.format("%s", <warning descr="Confusing 'null' argument to var-arg method">null</warning>);
|
||||
String.format("%s", <warning descr="Confusing argument 'null', unclear if a varargs or non-varargs call is desired">null</warning>);
|
||||
String.format("%d", 1);
|
||||
String.format("%s", <warning descr="Confusing argument 'ss', unclear if a varargs or non-varargs call is desired">ss</warning>);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -6,7 +6,7 @@ public class PrimitiveArrayArgumentToVariableArgMethod
|
||||
{
|
||||
public static void main(String[] arg) throws Throwable
|
||||
{
|
||||
methodVarArgObject(<warning descr="Confusing primitive array argument to var-arg method">new byte[3]</warning>);
|
||||
methodVarArgObject(<warning descr="Confusing primitive array argument to varargs method">new byte[3]</warning>);
|
||||
methodVarArgByteArray(new byte[3]);
|
||||
MethodHandle meh = null;
|
||||
meh.invokeExact(new int[] { });
|
||||
@@ -31,7 +31,7 @@ public class PrimitiveArrayArgumentToVariableArgMethod
|
||||
}
|
||||
|
||||
void m() {
|
||||
String.format("%s", <warning descr="Confusing primitive array argument to var-arg method">new int[]{1, 2, 3}</warning>);
|
||||
String.format("%s", <warning descr="Confusing primitive array argument to varargs method">new int[]{1, 2, 3}</warning>);
|
||||
}
|
||||
|
||||
static void bar1(java.lang.Object... objects) {
|
||||
@@ -48,7 +48,7 @@ public class PrimitiveArrayArgumentToVariableArgMethod
|
||||
|
||||
public static void invoke() {
|
||||
int[] ints = {1, 2, 3};
|
||||
bar1(<warning descr="Confusing primitive array argument to var-arg method">ints</warning>); // warn here
|
||||
bar1(<warning descr="Confusing primitive array argument to varargs method">ints</warning>); // warn here
|
||||
bar2(ints); // no warning needed here
|
||||
}
|
||||
}
|
||||
+2
@@ -2,12 +2,14 @@ package com.siyeh.igtest.j2me.private_member_access_between_outer_and_inner_clas
|
||||
|
||||
public class PrivateMemberAccessBetweenOuterAndInnerClass {
|
||||
private String caption = "Button";
|
||||
private final int N = 100;
|
||||
|
||||
private void initialize() {
|
||||
System.out.println(caption);
|
||||
Object btn = new Object() {
|
||||
public void foo() {
|
||||
System.out.println(<warning descr="Access to private member of class 'PrivateMemberAccessBetweenOuterAndInnerClass'">caption</warning>);
|
||||
System.out.println(N);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
+2
-2
@@ -7,7 +7,7 @@ public class MethodCanBeVariableArity {
|
||||
|
||||
public void method(String... s) {}
|
||||
|
||||
public void <warning descr="'convertMe()' can be converted to variable arity method">convertMe</warning>(String[] ss) {}
|
||||
public void <warning descr="'convertMe()' can be converted to varargs method">convertMe</warning>(String[] ss) {}
|
||||
|
||||
public void convertMeNot(byte[] bs) {}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ class Annotated {
|
||||
void m(String[] ss) {}
|
||||
}
|
||||
interface X {
|
||||
void <warning descr="'m()' can be converted to variable arity method">m</warning>(String[] ss);
|
||||
void <warning descr="'m()' can be converted to varargs method">m</warning>(String[] ss);
|
||||
}
|
||||
class Yes {
|
||||
void m(int[] is, int[] js) {}
|
||||
|
||||
+2
-1
@@ -117,7 +117,8 @@ public class ReplaceMethodRefWithLambdaIntention extends Intention {
|
||||
final String initialName;
|
||||
if (psiParameters != null) {
|
||||
final int idx = parameterIndex - (isReceiver ? 1 : 0);
|
||||
initialName = psiParameters[idx < psiParameters.length ? idx : psiParameters.length - 1].getName();
|
||||
initialName = psiParameters.length > 0 ? psiParameters[idx < psiParameters.length ? idx : psiParameters.length - 1].getName()
|
||||
: parameter.getName();
|
||||
}
|
||||
else {
|
||||
initialName = parameter.getName();
|
||||
|
||||
+17
-7
@@ -36,19 +36,29 @@ public class JavaFxFieldIdReferenceProvider extends JavaFxControllerBasedReferen
|
||||
protected PsiReference[] getReferencesByElement(@NotNull final PsiClass aClass,
|
||||
final XmlAttributeValue xmlAttributeValue,
|
||||
ProcessingContext context) {
|
||||
final PsiField field = aClass.findFieldByName(xmlAttributeValue.getValue(), true);
|
||||
return new PsiReference[]{new JavaFxControllerFieldRef(xmlAttributeValue, field, aClass)};
|
||||
final String name = xmlAttributeValue.getValue();
|
||||
PsiMember fieldOrGetterMethod = aClass.findFieldByName(name, true);
|
||||
if (fieldOrGetterMethod == null) {
|
||||
final PsiMethod[] methods = aClass.findMethodsByName(name, true);
|
||||
for (PsiMethod method : methods) {
|
||||
if (method.getParameterList().getParameters().length == 0) {
|
||||
fieldOrGetterMethod = method;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new PsiReference[]{new JavaFxControllerFieldRef(xmlAttributeValue, fieldOrGetterMethod, aClass)};
|
||||
}
|
||||
|
||||
public static class JavaFxControllerFieldRef extends PsiReferenceBase<XmlAttributeValue> {
|
||||
private final XmlAttributeValue myXmlAttributeValue;
|
||||
private final PsiField myField;
|
||||
private final PsiMember myFieldOrMethod;
|
||||
private final PsiClass myAClass;
|
||||
|
||||
public JavaFxControllerFieldRef(XmlAttributeValue xmlAttributeValue, PsiField field, PsiClass aClass) {
|
||||
public JavaFxControllerFieldRef(XmlAttributeValue xmlAttributeValue, PsiMember fieldOrMethod, PsiClass aClass) {
|
||||
super(xmlAttributeValue, true);
|
||||
myXmlAttributeValue = xmlAttributeValue;
|
||||
myField = field;
|
||||
myFieldOrMethod = fieldOrMethod;
|
||||
myAClass = aClass;
|
||||
}
|
||||
|
||||
@@ -63,11 +73,11 @@ public class JavaFxFieldIdReferenceProvider extends JavaFxControllerBasedReferen
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiElement resolve() {
|
||||
return myField != null ? myField : myXmlAttributeValue;
|
||||
return myFieldOrMethod != null ? myFieldOrMethod : myXmlAttributeValue;
|
||||
}
|
||||
|
||||
public boolean isUnresolved() {
|
||||
if (myField == null && myAClass != null) {
|
||||
if (myFieldOrMethod == null && myAClass != null) {
|
||||
final XmlFile xmlFile = (XmlFile)myXmlAttributeValue.getContainingFile();
|
||||
if (xmlFile.getRootTag() != null && !JavaFxPsiUtil.isOutOfHierarchy(myXmlAttributeValue)) {
|
||||
return true;
|
||||
|
||||
@@ -34,6 +34,5 @@
|
||||
</SOURCES>
|
||||
</library>
|
||||
</orderEntry>
|
||||
<orderEntry type="module" module-name="test-framework-java8" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -1,5 +1,6 @@
|
||||
add.import=Add Import
|
||||
class.to.import.chooser.title=Class to Import
|
||||
method.to.import.chooser.title=Method to Import
|
||||
access.static.via.class.reference.family=Access static via class reference
|
||||
access.static.via.class.reference.text=Access static ''{1}.{0}'' via class ''{2}'' reference
|
||||
add.default.constructor.family=Add Default Constructor
|
||||
|
||||
Reference in New Issue
Block a user