Merge remote-tracking branch 'origin/master'
@@ -218,6 +218,10 @@
|
||||
<option name="TAB_SIZE" value="8" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="JSON">
|
||||
<option name="KEEP_LINE_BREAKS" value="false" />
|
||||
<option name="PARENT_SETTINGS_INSTALLED" value="true" />
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="JSP">
|
||||
<indentOptions>
|
||||
<option name="INDENT_SIZE" value="2" />
|
||||
@@ -308,5 +312,4 @@
|
||||
</option>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</component>
|
||||
</project>
|
||||
|
||||
</project>
|
||||
@@ -3,7 +3,9 @@
|
||||
<extensionPoint name="regExpLanguageHost" beanClass="com.intellij.openapi.util.ClassExtensionPoint">
|
||||
<with attribute="implementationClass" implements="org.intellij.lang.regexp.RegExpLanguageHost"/>
|
||||
</extensionPoint>
|
||||
<extensionPoint name="regExpModifierProvider" interface="org.intellij.lang.regexp.RegExpModifierProvider"/>
|
||||
<extensionPoint name="regExpModifierProvider" beanClass="com.intellij.lang.LanguageExtensionPoint">
|
||||
<with attribute="implementationClass" implements="org.intellij.lang.regexp.RegExpModifierProvider"/>
|
||||
</extensionPoint>
|
||||
</extensionPoints>
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<lang.documentationProvider language="RegExp" implementationClass="org.intellij.lang.regexp.RegExpDocumentationProvider"/>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package org.intellij.lang.regexp;
|
||||
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.lang.LanguageExtension;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.intellij.lang.annotations.MagicConstant;
|
||||
@@ -28,7 +28,7 @@ import java.util.regex.Pattern;
|
||||
* @author Anna Bulenkova
|
||||
*/
|
||||
public interface RegExpModifierProvider {
|
||||
ExtensionPointName<RegExpModifierProvider> EP = new ExtensionPointName<RegExpModifierProvider>("com.intellij.regExpModifierProvider");
|
||||
LanguageExtension<RegExpModifierProvider> EP = new LanguageExtension<RegExpModifierProvider>("com.intellij.regExpModifierProvider");
|
||||
|
||||
@MagicConstant(flagsFromClass = Pattern.class)
|
||||
int getFlags(PsiElement elementInHost, PsiFile regexp);
|
||||
|
||||
@@ -40,6 +40,7 @@ import com.intellij.util.ui.UIUtil;
|
||||
import org.intellij.lang.regexp.RegExpLanguage;
|
||||
import org.intellij.lang.regexp.RegExpModifierProvider;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.CompoundBorder;
|
||||
@@ -53,6 +54,10 @@ import java.util.regex.Pattern;
|
||||
*/
|
||||
public class CheckRegExpForm {
|
||||
private static final String LAST_EDITED_REGEXP = "last.edited.regexp";
|
||||
|
||||
private static final JBColor BACKGROUND_COLOR_MATCH = new JBColor(new Color(231, 250, 219), new Color(68, 85, 66));
|
||||
private static final JBColor BACKGROUND_COLOR_NOMATCH = new JBColor(new Color(255, 177, 160), new Color(110, 43, 40));
|
||||
|
||||
private final PsiFile myRegexpFile;
|
||||
|
||||
private EditorTextField mySampleText; //TODO[kb]: make it multiline
|
||||
@@ -138,23 +143,33 @@ public class CheckRegExpForm {
|
||||
}
|
||||
|
||||
private void updateBalloon() {
|
||||
boolean correct = false;
|
||||
PsiLanguageInjectionHost host = InjectedLanguageUtil.findInjectionHost(myRegexpFile);
|
||||
boolean correct = isMatchingText(myRegexpFile, mySampleText.getText());
|
||||
|
||||
mySampleText.setBackground(correct ? BACKGROUND_COLOR_MATCH : BACKGROUND_COLOR_NOMATCH);
|
||||
myMessage.setText(correct ? "Matches!" : "no match");
|
||||
myRootPanel.revalidate();
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
public static boolean isMatchingTextTest(@NotNull PsiFile regexpFile, @NotNull String sampleText) {
|
||||
return isMatchingText(regexpFile, sampleText);
|
||||
}
|
||||
|
||||
private static boolean isMatchingText(@NotNull PsiFile regexpFile, @NotNull String sampleText) {
|
||||
final String regExp = regexpFile.getText();
|
||||
|
||||
PsiLanguageInjectionHost host = InjectedLanguageUtil.findInjectionHost(regexpFile);
|
||||
int flags = 0;
|
||||
if (host != null) {
|
||||
for (RegExpModifierProvider provider : RegExpModifierProvider.EP.getExtensions()) {
|
||||
flags = provider.getFlags(host, myRegexpFile);
|
||||
for (RegExpModifierProvider provider : RegExpModifierProvider.EP.allForLanguage(host.getLanguage())) {
|
||||
flags = provider.getFlags(host, regexpFile);
|
||||
if (flags > 0) break;
|
||||
}
|
||||
}
|
||||
try {
|
||||
correct = Pattern.compile(myRegExp.getText(), flags).matcher(mySampleText.getText()).matches();
|
||||
return Pattern.compile(regExp, flags).matcher(sampleText).matches();
|
||||
} catch (Exception ignore) {}
|
||||
|
||||
JBColor color1 = new JBColor(new Color(231, 250, 219), new Color(68, 85, 66));
|
||||
JBColor color2 = new JBColor(new Color(255, 177, 160), new Color(110, 43, 40));
|
||||
mySampleText.setBackground(correct ? color1 : color2);
|
||||
myMessage.setText(correct ? "Matches!" : "no match");
|
||||
myRootPanel.revalidate();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/scripts" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
<excludeFolder url="file://$MODULE_DIR$/restApiDocGenerator/node_modules" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
@@ -35,5 +36,4 @@
|
||||
<orderEntry type="module" module-name="groovy-jps-plugin" scope="RUNTIME" />
|
||||
<orderEntry type="module" module-name="groovy_rt" scope="RUNTIME" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
</module>
|
||||
@@ -1 +1,7 @@
|
||||
IDS_JDK_ONLY=true
|
||||
IDS_APP_TITLE=__IDE-NAME__ Launcher
|
||||
IDS_VM_OPTIONS_PATH=%USERPROFILE%\\.__PRODUCT_PATHS_SELECTOR__
|
||||
IDC_WINLAUNCHER=__IDE-NAME___LAUNCHER
|
||||
IDS_PROPS_ENV_VAR=__IDE-NAME___PROPERTIES
|
||||
IDS_VM_OPTIONS_ENV_VAR=__IDE-NAME___VM_OPTIONS
|
||||
IDS_ERROR_LAUNCHING_APP=Error launching __IDE-NAME__
|
||||
|
||||
@@ -1,2 +1,8 @@
|
||||
IDS_JDK_ONLY=true
|
||||
IDS_JDK_ENV_VAR=IDEA_JDK_64
|
||||
IDS_APP_TITLE=__IDE-NAME__ Launcher
|
||||
IDS_VM_OPTIONS_PATH=%USERPROFILE%\\.__PRODUCT_PATHS_SELECTOR__
|
||||
IDC_WINLAUNCHER=__IDE-NAME___LAUNCHER
|
||||
IDS_PROPS_ENV_VAR=__IDE-NAME___PROPERTIES
|
||||
IDS_VM_OPTIONS_ENV_VAR=__IDE-NAME___VM_OPTIONS
|
||||
IDS_ERROR_LAUNCHING_APP=Error launching __IDE-NAME__
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>rules</key>
|
||||
<dict>
|
||||
<key>^bin/</key>
|
||||
<true/>
|
||||
<key>^lib/</key>
|
||||
<true/>
|
||||
<key>^license/</key>
|
||||
<true/>
|
||||
<key>^MacOS/</key>
|
||||
<true/>
|
||||
<key>^plugins/</key>
|
||||
<true/>
|
||||
<key>^Resources/</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1 @@
|
||||
node_modules/
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"name": "IntelliJ Platform REST API",
|
||||
"version": "140.2110",
|
||||
"url" : "http://localhost:63342/rest"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
var gulp = require('gulp')
|
||||
var apidoc = require('gulp-apidoc')
|
||||
var path = require('path')
|
||||
|
||||
var sources = path.normalize("../../platform/platform-impl/src/org/jetbrains/ide")
|
||||
|
||||
gulp.task('apidoc', function () {
|
||||
apidoc.exec({src: sources, dest: (process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE) + "/idea-rest-api"})
|
||||
})
|
||||
|
||||
gulp.task('default', ['apidoc'])
|
||||
|
||||
gulp.task('watch', function() {
|
||||
gulp.watch(sources + "/**/*.{clj,coffee,cs,dart,erl,go,java,js,php,py,rb,ts,pm}", ['apidoc'])
|
||||
})
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"name": "restApiDocGenerator",
|
||||
"devDependencies": {
|
||||
"gulp": "^3.8.10",
|
||||
"gulp-apidoc": "^0.1.2"
|
||||
}
|
||||
}
|
||||
@@ -854,7 +854,8 @@ binding.setVariable("buildWinLauncher", { String ch, String inputPath, String ou
|
||||
if (pathsSelector != null) {
|
||||
def paths = getProperty("paths")
|
||||
def launcherPropertiesTemp = "${paths.sandbox}/launcher.properties"
|
||||
copyAndPatchFile(launcherProperties, launcherPropertiesTemp, ["PRODUCT_PATHS_SELECTOR": pathsSelector])
|
||||
copyAndPatchFile(launcherProperties, launcherPropertiesTemp, ["PRODUCT_PATHS_SELECTOR": pathsSelector,
|
||||
"IDE-NAME": p("component.names.product").toUpperCase()])
|
||||
launcherProperties = launcherPropertiesTemp
|
||||
}
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
package com.intellij.compiler;
|
||||
|
||||
import com.intellij.internal.statistic.AbstractApplicationUsagesCollector;
|
||||
import com.intellij.internal.statistic.CollectUsagesException;
|
||||
import com.intellij.internal.statistic.UsagesCollector;
|
||||
import com.intellij.internal.statistic.beans.GroupDescriptor;
|
||||
import com.intellij.internal.statistic.beans.UsageDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -30,12 +30,12 @@ import java.util.Set;
|
||||
* @author Eugene Zhuravlev
|
||||
* Date: 4/11/13
|
||||
*/
|
||||
public class CompilerSettingsUsageCollector extends UsagesCollector{
|
||||
public class CompilerSettingsUsageCollector extends AbstractApplicationUsagesCollector{
|
||||
public static final String GROUP_ID = "compiler";
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<UsageDescriptor> getUsages(@Nullable Project project) throws CollectUsagesException {
|
||||
public Set<UsageDescriptor> getProjectUsages(@Nullable Project project) throws CollectUsagesException {
|
||||
final CompilerWorkspaceConfiguration wsConfig = CompilerWorkspaceConfiguration.getInstance(project);
|
||||
|
||||
final Set<UsageDescriptor> result = new HashSet<UsageDescriptor>();
|
||||
|
||||
@@ -18,10 +18,10 @@ package com.intellij.compiler.impl;
|
||||
import com.intellij.compiler.ProblemsView;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.ide.errorTreeView.ErrorTreeElement;
|
||||
import com.intellij.ide.errorTreeView.ErrorTreeElementKind;
|
||||
import com.intellij.ide.errorTreeView.ErrorViewStructure;
|
||||
import com.intellij.ide.errorTreeView.GroupingElement;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.compiler.CompileScope;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
@@ -40,6 +40,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.ide.PooledThreadExecutor;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.EnumSet;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
@@ -48,7 +49,8 @@ import java.util.UUID;
|
||||
*/
|
||||
public class ProblemsViewImpl extends ProblemsView{
|
||||
private static final String PROBLEMS_TOOLWINDOW_ID = "Problems";
|
||||
|
||||
private static final EnumSet<ErrorTreeElementKind> ALL_MESSAGE_KINDS = EnumSet.allOf(ErrorTreeElementKind.class);
|
||||
|
||||
private final ProblemsViewPanel myPanel;
|
||||
private final SequentialTaskExecutor myViewUpdater = new SequentialTaskExecutor(PooledThreadExecutor.INSTANCE);
|
||||
private final Icon myActiveIcon = AllIcons.Toolwindows.Problems;
|
||||
@@ -70,7 +72,6 @@ public class ProblemsViewImpl extends ProblemsView{
|
||||
return;
|
||||
}
|
||||
final ToolWindow tw = wm.registerToolWindow(PROBLEMS_TOOLWINDOW_ID, false, ToolWindowAnchor.BOTTOM, project, true);
|
||||
updateIcon(false);
|
||||
final Content content = ContentFactory.SERVICE.getInstance().createContent(myPanel, "", false);
|
||||
// todo: setup content?
|
||||
tw.getContentManager().addContent(content);
|
||||
@@ -80,6 +81,7 @@ public class ProblemsViewImpl extends ProblemsView{
|
||||
tw.getContentManager().removeAllContents(true);
|
||||
}
|
||||
});
|
||||
updateIcon();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -89,19 +91,16 @@ public class ProblemsViewImpl extends ProblemsView{
|
||||
myViewUpdater.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateIcon(!cleanupChildrenRecursively(myPanel.getErrorViewStructure().getRootElement(), scope, currentSessionId));
|
||||
cleanupChildrenRecursively(myPanel.getErrorViewStructure().getRootElement(), scope, currentSessionId);
|
||||
updateIcon();
|
||||
myPanel.reload();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean cleanupChildrenRecursively(@NotNull final Object fromElement, final @Nullable CompileScope scope, @NotNull UUID currentSessionId) {
|
||||
private void cleanupChildrenRecursively(@NotNull final Object fromElement, final @Nullable CompileScope scope, @NotNull UUID currentSessionId) {
|
||||
final ErrorViewStructure structure = myPanel.getErrorViewStructure();
|
||||
ErrorTreeElement[] elements = structure.getChildElements(fromElement);
|
||||
if (elements.length ==0) return true;
|
||||
|
||||
boolean result = false;
|
||||
for (ErrorTreeElement element : elements) {
|
||||
for (ErrorTreeElement element : structure.getChildElements(fromElement)) {
|
||||
if (element instanceof GroupingElement) {
|
||||
if (scope != null) {
|
||||
final VirtualFile file = ((GroupingElement)element).getFile();
|
||||
@@ -111,20 +110,17 @@ public class ProblemsViewImpl extends ProblemsView{
|
||||
}
|
||||
if (!currentSessionId.equals(element.getData())) {
|
||||
structure.removeElement(element);
|
||||
result = true;
|
||||
}
|
||||
else {
|
||||
result |= cleanupChildrenRecursively(element, scope, currentSessionId);
|
||||
cleanupChildrenRecursively(element, scope, currentSessionId);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!currentSessionId.equals(element.getData())) {
|
||||
structure.removeElement(element);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -139,7 +135,7 @@ public class ProblemsViewImpl extends ProblemsView{
|
||||
public void run() {
|
||||
final ErrorViewStructure structure = myPanel.getErrorViewStructure();
|
||||
final GroupingElement group = structure.lookupGroupingElement(groupName);
|
||||
if (group != null && !sessionId.equals(group.getData())) {
|
||||
if (group != null && sessionId != null && !sessionId.equals(group.getData())) {
|
||||
structure.removeElement(group);
|
||||
}
|
||||
if (navigatable != null) {
|
||||
@@ -148,21 +144,24 @@ public class ProblemsViewImpl extends ProblemsView{
|
||||
else {
|
||||
myPanel.addMessage(type, text, null, -1, -1, sessionId);
|
||||
}
|
||||
updateIcon(true);
|
||||
updateIcon();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateIcon(final boolean active) {
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
private void updateIcon() {
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final ToolWindow tw = ToolWindowManager.getInstance(myProject).getToolWindow(PROBLEMS_TOOLWINDOW_ID);
|
||||
if (tw != null) {
|
||||
tw.setIcon(active ? myActiveIcon : myPassiveIcon);
|
||||
if (!myProject.isDisposed()) {
|
||||
final ToolWindow tw = ToolWindowManager.getInstance(myProject).getToolWindow(PROBLEMS_TOOLWINDOW_ID);
|
||||
if (tw != null) {
|
||||
final boolean active = myPanel.getErrorViewStructure().hasMessages(ALL_MESSAGE_KINDS);
|
||||
tw.setIcon(active ? myActiveIcon : myPassiveIcon);
|
||||
}
|
||||
}
|
||||
}
|
||||
}, myProject.getDisposed());
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,7 +21,7 @@ import com.intellij.openapi.project.Project;
|
||||
|
||||
public class ProblemsViewPanel extends NewErrorTreeViewPanel {
|
||||
public ProblemsViewPanel(Project project) {
|
||||
super(project, null, false, true, null);
|
||||
super(project, "reference.problems.tool.window", false, true, null);
|
||||
myTree.getEmptyText().setText("No compilation problems found");
|
||||
}
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ public class ProjectFromSourcesBuilderImpl extends ProjectImportBuilder implemen
|
||||
setBaseProjectPath(path);
|
||||
}
|
||||
|
||||
public List<Module> commit(final Project project, final ModifiableModuleModel model, final ModulesProvider modulesProvider) {
|
||||
public List<Module> commit(@NotNull final Project project, final ModifiableModuleModel model, final ModulesProvider modulesProvider) {
|
||||
final boolean fromProjectStructure = model != null;
|
||||
ModifiableModelsProvider modelsProvider = new IdeaModifiableModelsProvider();
|
||||
final LibraryTable.ModifiableModel projectLibraryTable = modelsProvider.getLibraryTableModifiableModel(project);
|
||||
|
||||
@@ -46,7 +46,9 @@ public abstract class LanguageLevelConfigurable implements UnnamedConfigurable {
|
||||
});
|
||||
myLanguageLevelCombo.insertItemAt(LanguageLevelCombo.USE_PROJECT_LANGUAGE_LEVEL, 0);
|
||||
|
||||
myPanel.add(new JLabel(ProjectBundle.message("module.module.language.level")),
|
||||
JLabel label = new JLabel(ProjectBundle.message("module.module.language.level"));
|
||||
label.setLabelFor(myLanguageLevelCombo);
|
||||
myPanel.add(label,
|
||||
new GridBagConstraints(0, 0, 1, 1, 0, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(12, 6, 12, 0), 0, 0));
|
||||
myPanel.add(myLanguageLevelCombo,
|
||||
new GridBagConstraints(1, 0, 1, 1, 1, 0, GridBagConstraints.NORTHWEST, GridBagConstraints.NONE, new Insets(6, 6, 12, 0), 0, 0));
|
||||
|
||||
@@ -56,7 +56,7 @@ public abstract class ProjectImportBuilder<T> extends ProjectBuilder {
|
||||
public abstract void setOpenProjectSettingsAfter(boolean on);
|
||||
|
||||
@Override
|
||||
public List<Module> commit(Project project, ModifiableModuleModel model, ModulesProvider modulesProvider) {
|
||||
public List<Module> commit(@NotNull Project project, ModifiableModuleModel model, ModulesProvider modulesProvider) {
|
||||
return commit(project, model, modulesProvider, null);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ public class SuppressParameterFix extends AbstractBatchSuppressByNoInspectionCom
|
||||
@Override
|
||||
public PsiElement getContainer(PsiElement context) {
|
||||
PsiParameter psiParameter = PsiTreeUtil.getParentOfType(context, PsiParameter.class, false);
|
||||
return psiParameter != null && JavaSuppressionUtil.canHave15Suppressions(psiParameter) ? psiParameter : null;
|
||||
return psiParameter != null && psiParameter.getTypeElement() != null && JavaSuppressionUtil.canHave15Suppressions(psiParameter) ? psiParameter : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1448,6 +1448,24 @@ public class HighlightUtil extends HighlightUtilBase {
|
||||
return HighlightClassUtil.reportIllegalEnclosingUsage(expr, null, aClass, expr);
|
||||
}
|
||||
|
||||
if (qualifier != null && aClass.isInterface() && languageLevel.isAtLeast(LanguageLevel.JDK_1_8)) {
|
||||
//15.12.1 for method invocation expressions; 15.13 for method references
|
||||
//If TypeName denotes an interface, I, then let T be the type declaration immediately enclosing the method reference expression.
|
||||
//It is a compile-time error if I is not a direct superinterface of T,
|
||||
//or if there exists some other direct superclass or direct superinterface of T, J, such that J is a subtype of I.
|
||||
final PsiClass classT = PsiTreeUtil.getParentOfType(expr, PsiClass.class);
|
||||
if (classT != null) {
|
||||
for (PsiClass superClass : classT.getSupers()) {
|
||||
if (superClass.isInterface() && //check spec-javac relations
|
||||
superClass.isInheritor(aClass, true)) {
|
||||
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR)
|
||||
.range(qualifier)
|
||||
.descriptionAndTooltip(JavaErrorMessages.message("bad.qualifier.in.super.method.reference", format(aClass), formatClass(superClass))).create();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (expr instanceof PsiThisExpression) {
|
||||
final PsiMethod psiMethod = PsiTreeUtil.getParentOfType(expr, PsiMethod.class);
|
||||
if (psiMethod == null || psiMethod.getContainingClass() != aClass && !isInsideDefaultMethod(psiMethod, aClass)) {
|
||||
|
||||
@@ -27,6 +27,8 @@ import com.intellij.openapi.projectRoots.JavaSdkVersion;
|
||||
import com.intellij.openapi.projectRoots.JdkVersionUtil;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.roots.*;
|
||||
import com.intellij.openapi.roots.ex.ProjectRootManagerEx;
|
||||
import com.intellij.openapi.util.EmptyRunnable;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.PsiFile;
|
||||
@@ -96,6 +98,7 @@ public class IncreaseLanguageLevelFix implements IntentionAction {
|
||||
}
|
||||
else {
|
||||
LanguageLevelProjectExtension.getInstance(project).setLanguageLevel(myLevel);
|
||||
ProjectRootManagerEx.getInstanceEx(project).makeRootsChange(EmptyRunnable.INSTANCE, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -94,12 +94,7 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
||||
final PsiElement lambdaContext = parent != null ? parent.getParent() : null;
|
||||
if (lambdaContext != null &&
|
||||
(LambdaUtil.isValidLambdaContext(lambdaContext) || !(lambdaContext instanceof PsiExpressionStatement)) &&
|
||||
canBeConvertedToLambda(aClass, new Condition<PsiClassType>() {
|
||||
@Override
|
||||
public boolean value(PsiClassType type) {
|
||||
return LambdaHighlightingUtil.checkInterfaceFunctional(type) == null;
|
||||
}
|
||||
})) {
|
||||
canBeConvertedToLambda(aClass, false)) {
|
||||
final PsiElement lBrace = aClass.getLBrace();
|
||||
LOG.assertTrue(lBrace != null);
|
||||
final TextRange rangeInElement = new TextRange(0, aClass.getStartOffsetInParent() + lBrace.getStartOffsetInParent());
|
||||
@@ -194,15 +189,18 @@ public class AnonymousCanBeLambdaInspection extends BaseJavaBatchLocalInspection
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean canBeConvertedToLambda(PsiAnonymousClass aClass, Condition<PsiClassType> baseClassTypeCondition) {
|
||||
if (PsiUtil.getLanguageLevel(aClass).isAtLeast(LanguageLevel.JDK_1_8) && baseClassTypeCondition.value(aClass.getBaseClassType())) {
|
||||
final PsiMethod[] methods = aClass.getMethods();
|
||||
if (methods.length == 1 && aClass.getFields().length == 0) {
|
||||
final PsiMethod method = methods[0];
|
||||
return method.getBody() != null &&
|
||||
!hasForbiddenRefsInsideBody(method, aClass) &&
|
||||
!hasRuntimeAnnotations(method) &&
|
||||
!method.hasModifierProperty(PsiModifier.SYNCHRONIZED);
|
||||
public static boolean canBeConvertedToLambda(PsiAnonymousClass aClass, boolean acceptParameterizedFunctionTypes) {
|
||||
if (PsiUtil.getLanguageLevel(aClass).isAtLeast(LanguageLevel.JDK_1_8)) {
|
||||
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(aClass.getBaseClassType());
|
||||
if (interfaceMethod != null && (acceptParameterizedFunctionTypes || !interfaceMethod.hasTypeParameters())) {
|
||||
final PsiMethod[] methods = aClass.getMethods();
|
||||
if (methods.length == 1 && aClass.getFields().length == 0) {
|
||||
final PsiMethod method = methods[0];
|
||||
return method.getBody() != null &&
|
||||
!hasForbiddenRefsInsideBody(method, aClass) &&
|
||||
!hasRuntimeAnnotations(method) &&
|
||||
!method.hasModifierProperty(PsiModifier.SYNCHRONIZED);
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -21,10 +21,8 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.RedundantCastUtil;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -67,12 +65,7 @@ public class AnonymousCanBeMethodReferenceInspection extends BaseJavaBatchLocalI
|
||||
@Override
|
||||
public void visitAnonymousClass(PsiAnonymousClass aClass) {
|
||||
super.visitAnonymousClass(aClass);
|
||||
if (AnonymousCanBeLambdaInspection.canBeConvertedToLambda(aClass, new Condition<PsiClassType>() {
|
||||
@Override
|
||||
public boolean value(PsiClassType type) {
|
||||
return LambdaUtil.isFunctionalType(type);
|
||||
}
|
||||
})) {
|
||||
if (AnonymousCanBeLambdaInspection.canBeConvertedToLambda(aClass, true)) {
|
||||
final PsiMethod method = aClass.getMethods()[0];
|
||||
final PsiCodeBlock body = method.getBody();
|
||||
final PsiCallExpression callExpression =
|
||||
|
||||
@@ -216,7 +216,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
) {
|
||||
DfaValue arrayVar = myFactory.createValue(((PsiArrayAccessExpression)lExpr).getArrayExpression());
|
||||
if (arrayVar instanceof DfaVariableValue) {
|
||||
addInstruction(new FlushVariableInstruction((DfaVariableValue)arrayVar));
|
||||
addInstruction(new FlushVariableInstruction((DfaVariableValue)arrayVar, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -690,6 +690,21 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
finishElement(switchStmt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMethodReferenceExpression(PsiMethodReferenceExpression expression) {
|
||||
startElement(expression);
|
||||
|
||||
PsiExpression qualifier = expression.getQualifierExpression();
|
||||
if (qualifier != null) {
|
||||
qualifier.accept(this);
|
||||
addInstruction(new FieldReferenceInstruction(qualifier, "Method reference qualifier"));
|
||||
}
|
||||
|
||||
addInstruction(new PushInstruction(myFactory.createTypeValue(expression.getFunctionalInterfaceType(), Nullness.NOT_NULL), expression));
|
||||
|
||||
finishElement(expression);
|
||||
}
|
||||
|
||||
@Override public void visitSynchronizedStatement(PsiSynchronizedStatement statement) {
|
||||
startElement(statement);
|
||||
|
||||
|
||||
@@ -123,7 +123,14 @@ public abstract class InstructionVisitor {
|
||||
public DfaInstructionState[] visitFlushVariable(FlushVariableInstruction instruction, DataFlowRunner runner, DfaMemoryState memState) {
|
||||
final DfaVariableValue variable = instruction.getVariable();
|
||||
if (variable != null) {
|
||||
memState.flushVariable(variable);
|
||||
if (instruction.isDependentsOnly()) {
|
||||
for (DfaVariableValue qualified : runner.getFactory().getVarFactory().getAllQualifiedBy(variable)) {
|
||||
memState.flushVariable(qualified);
|
||||
}
|
||||
}
|
||||
else {
|
||||
memState.flushVariable(variable);
|
||||
}
|
||||
} else {
|
||||
memState.flushFields();
|
||||
}
|
||||
|
||||
@@ -29,9 +29,19 @@ import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
|
||||
|
||||
public class FlushVariableInstruction extends Instruction {
|
||||
private final DfaVariableValue myVariable;
|
||||
private final boolean myDependentsOnly;
|
||||
|
||||
public FlushVariableInstruction(DfaVariableValue expr) {
|
||||
myVariable = expr;
|
||||
this(expr, false);
|
||||
}
|
||||
|
||||
public FlushVariableInstruction(DfaVariableValue variable, boolean dependentsOnly) {
|
||||
myVariable = variable;
|
||||
myDependentsOnly = dependentsOnly;
|
||||
}
|
||||
|
||||
public boolean isDependentsOnly() {
|
||||
return myDependentsOnly;
|
||||
}
|
||||
|
||||
public DfaVariableValue getVariable() {
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.intellij.codeInsight;
|
||||
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiExpressionList;
|
||||
import com.intellij.psi.PsiFile;
|
||||
@@ -30,14 +29,12 @@ import org.intellij.lang.regexp.RegExpModifierProvider;
|
||||
public class JavaRegExpModifierProvider implements RegExpModifierProvider {
|
||||
@Override
|
||||
public int getFlags(PsiElement elementInHost, PsiFile regexp) {
|
||||
if (elementInHost.getLanguage() == JavaLanguage.INSTANCE) {
|
||||
final PsiExpressionList list = PsiTreeUtil.getParentOfType(elementInHost, PsiExpressionList.class);
|
||||
if (list != null && list.getExpressions().length == 2 && list.getExpressionTypes()[1] == PsiType.INT) {
|
||||
final Object result = JavaConstantExpressionEvaluator.computeConstantExpression(list.getExpressions()[1], false);
|
||||
if (result instanceof Integer) {
|
||||
//noinspection MagicConstant
|
||||
return ((Integer)result).intValue();
|
||||
}
|
||||
final PsiExpressionList list = PsiTreeUtil.getParentOfType(elementInHost, PsiExpressionList.class);
|
||||
if (list != null && list.getExpressions().length == 2 && list.getExpressionTypes()[1] == PsiType.INT) {
|
||||
final Object result = JavaConstantExpressionEvaluator.computeConstantExpression(list.getExpressions()[1], false);
|
||||
if (result instanceof Integer) {
|
||||
//noinspection MagicConstant
|
||||
return ((Integer)result).intValue();
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
package com.intellij.openapi.roots.impl;
|
||||
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.module.LanguageLevelUtil;
|
||||
import com.intellij.openapi.module.EffectiveLanguageLevelUtil;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
@@ -70,7 +70,7 @@ public class JavaLanguageLevelPusher implements FilePropertyPusher<LanguageLevel
|
||||
|
||||
@Override
|
||||
public LanguageLevel getImmediateValue(@NotNull Module module) {
|
||||
return LanguageLevelUtil.getEffectiveLanguageLevel(module);
|
||||
return EffectiveLanguageLevelUtil.getEffectiveLanguageLevel(module);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -47,6 +47,7 @@ import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.*;
|
||||
import com.intellij.psi.controlFlow.ControlFlowUtil;
|
||||
@@ -636,7 +637,7 @@ public class ExtractMethodProcessor implements MatchProvider {
|
||||
prepareMethodBody(emptyMethod, false);
|
||||
final NullableNotNullManager manager = NullableNotNullManager.getInstance(myProject);
|
||||
final PsiClass nullableAnnotationClass = JavaPsiFacade.getInstance(myProject)
|
||||
.findClass(manager.getDefaultNullable(), GlobalSearchScope.allScope(myProject));
|
||||
.findClass(manager.getDefaultNullable(), myElements[0].getResolveScope());
|
||||
if (nullableAnnotationClass != null) {
|
||||
if (myNotNullConditionalCheck || myNullConditionalCheck) {
|
||||
return Nullness.NULLABLE;
|
||||
@@ -670,6 +671,10 @@ public class ExtractMethodProcessor implements MatchProvider {
|
||||
final List<String> getters = new ArrayList<String>(ContainerUtil.map(initialMethodNames, new Function<String, String>() {
|
||||
@Override
|
||||
public String fun(String propertyName) {
|
||||
if (!PsiNameHelper.getInstance(myProject).isIdentifier(propertyName)) {
|
||||
LOG.info(propertyName + "; " + myExpression);
|
||||
return null;
|
||||
}
|
||||
return GenerateMembersUtil.suggestGetterName(propertyName, myReturnType, myProject);
|
||||
}
|
||||
}));
|
||||
|
||||
@@ -297,7 +297,7 @@ public class GenericsUtil {
|
||||
}
|
||||
else if (substituted instanceof PsiCapturedWildcardType) {
|
||||
final PsiType extendsBound = ((PsiCapturedWildcardType)substituted).getUpperBound();
|
||||
if (acceptExtendsBound(extendsType, extendsBound)) {
|
||||
if (acceptExtendsBound(extendsType, extendsBound) || extendsType.equals(substitutor.substitute(extendsBound))) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,4 +31,19 @@ public interface PsiFunctionalExpression extends PsiExpression, Iconable, Naviga
|
||||
* @return true if assignment SAM s = expr is correctly shaped
|
||||
*/
|
||||
boolean isAcceptable(PsiType left);
|
||||
|
||||
/**
|
||||
* Potentially compatible check takes into account the presence and "shape" of functional interface target types.
|
||||
*
|
||||
* JLS placement:
|
||||
* 15.12.2.1 Identify Potentially Applicable Methods
|
||||
* A member method is potentially applicable to a method invocation if and only if all of the following are true:
|
||||
* The name of the member is identical to the name of the method in the method invocation.
|
||||
* The member is accessible (§6.6) to the class or interface in which the method invocation appears.
|
||||
* If the member is a fixed arity method with arity n, the arity of the method invocation is equal to n,
|
||||
* and for all i (1 ≤ i ≤ n), the i'th argument of the method invocation is potentially compatible, as defined below,
|
||||
* with the type of the i'th parameter of the method.
|
||||
* If the member is a variable arity method with arity n, etc
|
||||
*/
|
||||
boolean isPotentiallyCompatible(PsiType left);
|
||||
}
|
||||
|
||||
@@ -46,4 +46,12 @@ public interface PsiLambdaExpression extends PsiFunctionalExpression {
|
||||
* @return true when lambda declares parameter types explicitly
|
||||
*/
|
||||
boolean hasFormalParameterTypes();
|
||||
|
||||
/**
|
||||
* A lambda expression (§15.27) is potentially compatible with a functional interface type (§9.8) if all of the following are true:
|
||||
* The arity of the target type's function type is the same as the arity of the lambda expression.
|
||||
* If the target type's function type has a void return, then the lambda body is either a statement expression (§14.8) or a void-compatible block (§15.27.2).
|
||||
* If the target type's function type has a (non-void) return type, then the lambda body is either an expression or a value-compatible block (§15.27.2).
|
||||
*/
|
||||
boolean isPotentiallyCompatible(PsiType left);
|
||||
}
|
||||
|
||||
@@ -175,10 +175,7 @@ public class PsiMethodReferenceUtil {
|
||||
if (resolve instanceof PsiClass) {
|
||||
containingClass = (PsiClass)resolve;
|
||||
substitutor = resolveResult.getSubstitutor();
|
||||
final boolean isRawSubst = !methodReferenceExpression.isConstructor() &&
|
||||
PsiTreeUtil.isAncestor(containingClass, methodReferenceExpression, true) &&
|
||||
PsiUtil.isRawSubstitutor(containingClass, substitutor);
|
||||
return new QualifierResolveResult(containingClass, isRawSubst ? PsiSubstitutor.EMPTY : substitutor, true);
|
||||
return new QualifierResolveResult(containingClass, substitutor, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,11 +52,16 @@ public class FunctionalInterfaceParameterizationUtil {
|
||||
|
||||
@Nullable
|
||||
public static PsiType getGroundTargetType(@Nullable PsiType psiClassType, @Nullable PsiLambdaExpression expr) {
|
||||
return getGroundTargetType(psiClassType, expr, true);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiType getGroundTargetType(@Nullable PsiType psiClassType, @Nullable PsiLambdaExpression expr, boolean performFinalCheck) {
|
||||
if (!isWildcardParameterized(psiClassType)) {
|
||||
return psiClassType;
|
||||
}
|
||||
|
||||
if (expr != null && expr.hasFormalParameterTypes()) return getFunctionalTypeExplicit(psiClassType, expr);
|
||||
if (expr != null && expr.hasFormalParameterTypes()) return getFunctionalTypeExplicit(psiClassType, expr, performFinalCheck);
|
||||
|
||||
return psiClassType instanceof PsiClassType ? getNonWildcardParameterization((PsiClassType)psiClassType) : null;
|
||||
}
|
||||
@@ -64,11 +69,11 @@ public class FunctionalInterfaceParameterizationUtil {
|
||||
/**
|
||||
* 18.5.3. Functional Interface Parameterization Inference
|
||||
*/
|
||||
private static PsiType getFunctionalTypeExplicit(PsiType psiClassType, PsiLambdaExpression expr) {
|
||||
private static PsiType getFunctionalTypeExplicit(PsiType psiClassType, PsiLambdaExpression expr, boolean performFinalCheck) {
|
||||
final PsiParameter[] lambdaParams = expr.getParameterList().getParameters();
|
||||
if (psiClassType instanceof PsiIntersectionType) {
|
||||
for (PsiType psiType : ((PsiIntersectionType)psiClassType).getConjuncts()) {
|
||||
final PsiType functionalType = getFunctionalTypeExplicit(psiType, expr);
|
||||
final PsiType functionalType = getFunctionalTypeExplicit(psiType, expr, performFinalCheck);
|
||||
if (functionalType != null) return functionalType;
|
||||
}
|
||||
return null;
|
||||
@@ -120,12 +125,12 @@ public class FunctionalInterfaceParameterizationUtil {
|
||||
|
||||
//If F<A'1, ..., A'm> is not a well-formed type (that is, the type arguments are not within their bounds),
|
||||
// or if F<A'1, ..., A'm> is not a subtype of F<A1, ..., Am>, no valid parameterization exists.
|
||||
if (!isWellFormed(psiClass, typeParameters, newTypeParameters)) {
|
||||
if (!isWellFormed(psiClass, typeParameters, newTypeParameters) || performFinalCheck && !psiClassType.isAssignableFrom(parameterization)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//Otherwise, the inferred parameterization is either F<A'1, ..., A'm>, if all the type arguments are types,
|
||||
if (!TypeConversionUtil.containsWildcards(parameterization) && psiClassType.isAssignableFrom(parameterization)) {
|
||||
if (!TypeConversionUtil.containsWildcards(parameterization)) {
|
||||
return parameterization;
|
||||
}
|
||||
|
||||
|
||||
@@ -1130,11 +1130,11 @@ public class InferenceSession {
|
||||
final PsiType pType = signature.getParameterTypes()[0];
|
||||
|
||||
PsiSubstitutor psiSubstitutor = qualifierResolveResult.getSubstitutor();
|
||||
// 15.28.1 If the ReferenceType is a raw type, and there exists a parameterization of this type, T, that is a supertype of P1,
|
||||
// 15.13.1 If the ReferenceType is a raw type, and there exists a parameterization of this type, T, that is a supertype of P1,
|
||||
// the type to search is the result of capture conversion (5.1.10) applied to T;
|
||||
// otherwise, the type to search is the same as the type of the first search. Again, the type arguments, if any, are given by the method reference.
|
||||
if (PsiUtil.isRawSubstitutor(containingClass, qualifierResolveResult.getSubstitutor())) {
|
||||
final PsiClassType.ClassResolveResult pResult = PsiUtil.resolveGenericsClassInType(pType);
|
||||
if (PsiUtil.isRawSubstitutor(containingClass, psiSubstitutor)) {
|
||||
final PsiClassType.ClassResolveResult pResult = PsiUtil.resolveGenericsClassInType(PsiUtil.captureToplevelWildcards(pType, myContext));
|
||||
final PsiClass pClass = pResult.getElement();
|
||||
final PsiSubstitutor receiverSubstitutor = pClass != null ? TypeConversionUtil
|
||||
.getClassSubstitutor(containingClass, pClass, pResult.getSubstitutor()) : null;
|
||||
@@ -1267,7 +1267,7 @@ public class InferenceSession {
|
||||
|
||||
final List<PsiExpression> returnExpressions = LambdaUtil.getReturnExpressions((PsiLambdaExpression)arg);
|
||||
|
||||
if (LambdaUtil.isFunctionalType(sReturnType) && LambdaUtil.isFunctionalType(tReturnType) &&
|
||||
if (LambdaUtil.isFunctionalType(sReturnType) && LambdaUtil.isFunctionalType(tReturnType) &&
|
||||
!TypeConversionUtil.isAssignable(TypeConversionUtil.erasure(sReturnType), TypeConversionUtil.erasure(tReturnType)) &&
|
||||
!TypeConversionUtil.isAssignable(TypeConversionUtil.erasure(tReturnType), TypeConversionUtil.erasure(sReturnType))) {
|
||||
|
||||
@@ -1293,6 +1293,9 @@ public class InferenceSession {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (sPrimitive) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -1308,11 +1311,17 @@ public class InferenceSession {
|
||||
if (arg instanceof PsiMethodReferenceExpression && ((PsiMethodReferenceExpression)arg).isExact()) {
|
||||
final PsiParameter[] sParameters = sInterfaceMethod.getParameterList().getParameters();
|
||||
final PsiParameter[] tParameters = tInterfaceMethod.getParameterList().getParameters();
|
||||
if (session != null) {
|
||||
LOG.assertTrue(sParameters.length == tParameters.length);
|
||||
for (int i = 0; i < tParameters.length; i++) {
|
||||
session.addConstraint(new TypeEqualityConstraint(tSubstitutor.substitute(tParameters[i].getType()),
|
||||
sSubstitutor.substitute(sParameters[i].getType())));
|
||||
LOG.assertTrue(sParameters.length == tParameters.length);
|
||||
for (int i = 0; i < tParameters.length; i++) {
|
||||
final PsiType tSubstituted = tSubstitutor.substitute(tParameters[i].getType());
|
||||
final PsiType sSubstituted = sSubstitutor.substitute(sParameters[i].getType());
|
||||
if (session != null) {
|
||||
session.addConstraint(new TypeEqualityConstraint(tSubstituted, sSubstituted));
|
||||
}
|
||||
else {
|
||||
if (!Comparing.equal(tSubstituted, sSubstituted)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
final PsiType sReturnType = sSubstitutor.substitute(sInterfaceMethod.getReturnType());
|
||||
@@ -1412,8 +1421,7 @@ public class InferenceSession {
|
||||
}
|
||||
|
||||
public PsiType substituteWithInferenceVariables(PsiType type) {
|
||||
final PsiType substituted = myInferenceSubstitution.substitute(type);
|
||||
return isProperType(substituted) ? type : substituted;
|
||||
return myInferenceSubstitution.substitute(type);
|
||||
}
|
||||
|
||||
public InferenceSession findNestedCallSession(PsiExpression arg) {
|
||||
|
||||
@@ -50,7 +50,7 @@ public abstract class InputOutputConstraintFormula implements ConstraintFormula
|
||||
if (LambdaUtil.isFunctionalType(type)) {
|
||||
final PsiType functionType =
|
||||
psiExpression instanceof PsiLambdaExpression
|
||||
? FunctionalInterfaceParameterizationUtil.getGroundTargetType(type, (PsiLambdaExpression)psiExpression)
|
||||
? FunctionalInterfaceParameterizationUtil.getGroundTargetType(type, (PsiLambdaExpression)psiExpression, false)
|
||||
: type;
|
||||
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(functionType);
|
||||
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult);
|
||||
|
||||
@@ -26,7 +26,7 @@ public class LambdaExpressionCompatibilityConstraint implements ConstraintFormul
|
||||
return false;
|
||||
}
|
||||
|
||||
final PsiType groundTargetType = FunctionalInterfaceParameterizationUtil.getGroundTargetType(myT, myExpression);
|
||||
final PsiType groundTargetType = FunctionalInterfaceParameterizationUtil.getGroundTargetType(myT, myExpression, false);
|
||||
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(groundTargetType);
|
||||
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult);
|
||||
if (interfaceMethod == null) {
|
||||
@@ -56,11 +56,11 @@ public class LambdaExpressionCompatibilityConstraint implements ConstraintFormul
|
||||
if (returnType != null) {
|
||||
final List<PsiExpression> returnExpressions = LambdaUtil.getReturnExpressions(myExpression);
|
||||
if (returnType.equals(PsiType.VOID)) {
|
||||
if (!returnExpressions.isEmpty() && !(myExpression.getBody() instanceof PsiExpression)) {
|
||||
if (!myExpression.isVoidCompatible()) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (returnExpressions.isEmpty() && !myExpression.isValueCompatible()) { //not value-compatible
|
||||
if (!myExpression.isValueCompatible()) {
|
||||
return false;
|
||||
}
|
||||
InferenceSession callsession = session.findNestedCallSession(myExpression);
|
||||
|
||||
@@ -63,16 +63,10 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
|
||||
|
||||
final PsiMethodReferenceUtil.QualifierResolveResult qualifierResolveResult = PsiMethodReferenceUtil.getQualifierResolveResult(myExpression);
|
||||
|
||||
if (!myExpression.isExact()) {
|
||||
for (PsiParameter parameter : targetParameters) {
|
||||
if (!session.isProperType(substitutor.substitute(parameter.getType()))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (myExpression.isExact()) {
|
||||
final PsiMember applicableMember = myExpression.getPotentiallyApplicableMember();
|
||||
LOG.assertTrue(applicableMember != null);
|
||||
|
||||
|
||||
final PsiClass applicableMemberContainingClass = applicableMember.getContainingClass();
|
||||
final PsiClass containingClass = qualifierResolveResult.getContainingClass();
|
||||
|
||||
@@ -90,7 +84,13 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
|
||||
}
|
||||
final PsiParameter[] parameters = applicableMember instanceof PsiMethod ? ((PsiMethod)applicableMember).getParameterList().getParameters() : PsiParameter.EMPTY_ARRAY;
|
||||
if (targetParameters.length == parameters.length + 1) {
|
||||
specialCase(session, constraints, substitutor, targetParameters, true);
|
||||
final PsiType qualifierType = PsiMethodReferenceUtil.getQualifierType(myExpression);
|
||||
final PsiClass qualifierClass = PsiUtil.resolveClassInType(qualifierType);
|
||||
if (qualifierClass != null) {
|
||||
session.initBounds(myExpression, qualifierClass.getTypeParameters());
|
||||
final PsiType pType = substitutor.substitute(targetParameters[0].getType());
|
||||
constraints.add(new StrictSubtypingConstraint(session.substituteWithInferenceVariables(qualifierType), pType));
|
||||
}
|
||||
for (int i = 1; i < targetParameters.length; i++) {
|
||||
constraints.add(new TypeCompatibilityConstraint(session.substituteWithInferenceVariables(psiSubstitutor.substitute(parameters[i - 1].getType())),
|
||||
substitutor.substitute(targetParameters[i].getType())));
|
||||
@@ -123,6 +123,14 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
|
||||
return true;
|
||||
}
|
||||
|
||||
//------ non exact method references --------------------
|
||||
|
||||
for (PsiParameter parameter : targetParameters) {
|
||||
if (!session.isProperType(substitutor.substitute(parameter.getType()))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
final Map<PsiElement, PsiType> map = LambdaUtil.getFunctionalTypeMap();
|
||||
final PsiType added = map.put(myExpression, session.startWithFreshVars(groundTargetType));
|
||||
final JavaResolveResult resolve;
|
||||
@@ -148,14 +156,28 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
|
||||
final PsiType referencedMethodReturnType;
|
||||
final PsiClass containingClass = method.getContainingClass();
|
||||
LOG.assertTrue(containingClass != null, method);
|
||||
PsiClass qContainingClass = qualifierResolveResult.getContainingClass();
|
||||
final PsiClass qContainingClass = qualifierResolveResult.getContainingClass();
|
||||
PsiSubstitutor psiSubstitutor = qualifierResolveResult.getSubstitutor();
|
||||
if (qContainingClass != null) {
|
||||
// 15.13.1 If the ReferenceType is a raw type, and there exists a parameterization of this type, T, that is a supertype of P1,
|
||||
// the type to search is the result of capture conversion (5.1.10) applied to T;
|
||||
// otherwise, the type to search is the same as the type of the first search. Again, the type arguments, if any, are given by the method reference.
|
||||
if ( PsiUtil.isRawSubstitutor(qContainingClass, psiSubstitutor)) {
|
||||
psiSubstitutor = PsiSubstitutor.EMPTY;
|
||||
if (targetParameters.length == method.getParameterList().getParametersCount() + 1) {
|
||||
final PsiType pType = substitutor.substitute(targetParameters[0].getType());
|
||||
PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(PsiUtil.captureToplevelWildcards(pType, myExpression));
|
||||
PsiClass paramClass = resolveResult.getElement();
|
||||
LOG.assertTrue(paramClass != null);
|
||||
psiSubstitutor = TypeConversionUtil.getClassSubstitutor(qContainingClass, paramClass, resolveResult.getSubstitutor());
|
||||
LOG.assertTrue(psiSubstitutor != null);
|
||||
}
|
||||
else {
|
||||
psiSubstitutor = PsiSubstitutor.EMPTY;
|
||||
}
|
||||
}
|
||||
|
||||
if (qContainingClass.isInheritor(containingClass, true)) {
|
||||
psiSubstitutor = TypeConversionUtil.getClassSubstitutor(containingClass, qContainingClass, PsiSubstitutor.EMPTY);
|
||||
psiSubstitutor = TypeConversionUtil.getClassSubstitutor(containingClass, qContainingClass, psiSubstitutor);
|
||||
LOG.assertTrue(psiSubstitutor != null);
|
||||
}
|
||||
}
|
||||
@@ -202,52 +224,13 @@ public class PsiMethodReferenceCompatibilityConstraint implements ConstraintForm
|
||||
}
|
||||
}
|
||||
|
||||
final PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
if (targetParameters.length == parameters.length + 1 && !method.isVarArgs() &&
|
||||
PsiPolyExpressionUtil.mentionsTypeParameters(referencedMethodReturnType, ContainerUtil.newHashSet(containingClass.getTypeParameters()))) { //todo specification bug?
|
||||
specialCase(session, constraints, substitutor, targetParameters, false);
|
||||
}
|
||||
constraints.add(new TypeCompatibilityConstraint(returnType, session.substituteWithInferenceVariables(psiSubstitutor.substitute(referencedMethodReturnType))));
|
||||
constraints.add(new TypeCompatibilityConstraint(returnType,
|
||||
session.substituteWithInferenceVariables(psiSubstitutor.substitute(referencedMethodReturnType))));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void specialCase(InferenceSession session,
|
||||
List<ConstraintFormula> constraints,
|
||||
PsiSubstitutor substitutor,
|
||||
PsiParameter[] targetParameters,
|
||||
boolean ignoreRaw) {
|
||||
final PsiElement qualifier = myExpression.getQualifier();
|
||||
PsiType qualifierType = null;
|
||||
if (qualifier instanceof PsiTypeElement) {
|
||||
qualifierType = ((PsiTypeElement)qualifier).getType();
|
||||
final PsiClass qualifierClass = PsiUtil.resolveClassInType(qualifierType);
|
||||
if (qualifierClass != null) {
|
||||
qualifierType = JavaPsiFacade.getElementFactory(myExpression.getProject()).createType(qualifierClass, PsiSubstitutor.EMPTY);
|
||||
}
|
||||
}
|
||||
else if (qualifier instanceof PsiExpression) {
|
||||
qualifierType = ((PsiExpression)qualifier).getType();
|
||||
if (qualifierType == null && qualifier instanceof PsiReferenceExpression) {
|
||||
final JavaResolveResult resolveResult = ((PsiReferenceExpression)qualifier).advancedResolve(false);
|
||||
final PsiElement res = resolveResult.getElement();
|
||||
if (res instanceof PsiClass) {
|
||||
PsiClass containingClass = (PsiClass)res;
|
||||
final boolean isRawSubst = !ignoreRaw && !myExpression.isConstructor() && PsiUtil.isRawSubstitutor(containingClass, resolveResult.getSubstitutor());
|
||||
qualifierType = JavaPsiFacade.getElementFactory(res.getProject()).createType(containingClass, isRawSubst ? PsiSubstitutor.EMPTY : resolveResult.getSubstitutor());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final PsiClass qualifierClass = PsiUtil.resolveClassInType(qualifierType);
|
||||
if (qualifierClass != null) {
|
||||
session.initBounds(myExpression, qualifierClass.getTypeParameters());
|
||||
constraints.add(new StrictSubtypingConstraint(session.substituteWithInferenceVariables(qualifierType),
|
||||
session.substituteWithInferenceVariables(substitutor.substitute(targetParameters[0].getType()))));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(PsiSubstitutor substitutor, boolean cache) {
|
||||
myT = substitutor.substitute(myT);
|
||||
|
||||
@@ -100,7 +100,8 @@ public class MethodReferenceResolver implements ResolveCache.PolyVariantContextR
|
||||
final PsiExpressionList argumentList = getArgumentList();
|
||||
final PsiType[] typeParameters = reference.getTypeParameters();
|
||||
return new MethodCandidateInfo(method, substitutor, !accessible, staticProblem, argumentList, myCurrentFileContext,
|
||||
argumentList != null ? argumentList.getExpressionTypes() : null, typeParameters.length > 0 ? typeParameters : null,
|
||||
argumentList != null ? argumentList.getExpressionTypes() : null,
|
||||
method.hasTypeParameters() && typeParameters.length > 0 ? typeParameters : null,
|
||||
getLanguageLevel()) {
|
||||
@Override
|
||||
public boolean isVarargs() {
|
||||
|
||||
@@ -177,9 +177,6 @@ public class PsiLambdaExpressionImpl extends ExpressionPsiElement implements Psi
|
||||
}
|
||||
final PsiExpressionList argsList = PsiTreeUtil.getParentOfType(this, PsiExpressionList.class);
|
||||
|
||||
leftType = FunctionalInterfaceParameterizationUtil.getGroundTargetType(leftType, this);
|
||||
|
||||
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(leftType);
|
||||
if (MethodCandidateInfo.ourOverloadGuard.currentStack().contains(argsList)) {
|
||||
final MethodCandidateInfo.CurrentCandidateProperties candidateProperties = MethodCandidateInfo.getCurrentMethod(argsList);
|
||||
if (candidateProperties != null) {
|
||||
@@ -194,6 +191,7 @@ public class PsiLambdaExpressionImpl extends ExpressionPsiElement implements Psi
|
||||
}
|
||||
}
|
||||
|
||||
leftType = FunctionalInterfaceParameterizationUtil.getGroundTargetType(leftType, this);
|
||||
if (!isPotentiallyCompatible(leftType)) {
|
||||
return false;
|
||||
}
|
||||
@@ -202,9 +200,12 @@ public class PsiLambdaExpressionImpl extends ExpressionPsiElement implements Psi
|
||||
return true;
|
||||
}
|
||||
|
||||
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(leftType);
|
||||
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(resolveResult);
|
||||
if (interfaceMethod == null) return false;
|
||||
|
||||
if (interfaceMethod.hasTypeParameters()) return false;
|
||||
|
||||
final PsiSubstitutor substitutor = LambdaUtil.getSubstitutor(interfaceMethod, resolveResult);
|
||||
|
||||
if (hasFormalParameterTypes()) {
|
||||
@@ -239,11 +240,8 @@ public class PsiLambdaExpressionImpl extends ExpressionPsiElement implements Psi
|
||||
return true;
|
||||
}
|
||||
|
||||
//A lambda expression (§15.27) is potentially compatible with a functional interface type (§9.8) if all of the following are true:
|
||||
// The arity of the target type's function type is the same as the arity of the lambda expression.
|
||||
// If the target type's function type has a void return, then the lambda body is either a statement expression (§14.8) or a void-compatible block (§15.27.2).
|
||||
// If the target type's function type has a (non-void) return type, then the lambda body is either an expression or a value-compatible block (§15.27.2).
|
||||
private boolean isPotentiallyCompatible(PsiType left) {
|
||||
@Override
|
||||
public boolean isPotentiallyCompatible(PsiType left) {
|
||||
final PsiMethod interfaceMethod = LambdaUtil.getFunctionalInterfaceMethod(left);
|
||||
if (interfaceMethod == null) return false;
|
||||
|
||||
|
||||
@@ -488,7 +488,7 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
|
||||
methodReturnType = JavaPsiFacade.getElementFactory(getProject()).createType(containingClass, subst);
|
||||
}
|
||||
|
||||
return TypeConversionUtil.isAssignable(interfaceReturnType, methodReturnType, false);
|
||||
return TypeConversionUtil.isAssignable(interfaceReturnType, methodReturnType);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -388,3 +388,4 @@ feature.method.references=Method references
|
||||
feature.lambda.expressions=Lambda expressions
|
||||
feature.type.annotations=Type annotations
|
||||
insufficient.language.level={0} are not supported at this language level
|
||||
bad.qualifier.in.super.method.reference=Bad type qualifier in default super call: redundant interface {0} is extended by {1}
|
||||
|
||||
@@ -33,5 +33,6 @@
|
||||
<orderEntry type="module" module-name="xml-psi-impl" scope="TEST" />
|
||||
<orderEntry type="module" module-name="properties-psi-api" scope="TEST" />
|
||||
<orderEntry type="module" module-name="java-decompiler-plugin" scope="TEST" />
|
||||
<orderEntry type="module" module-name="RegExpSupport" scope="TEST" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -0,0 +1,11 @@
|
||||
interface I {
|
||||
default void m() {}
|
||||
|
||||
}
|
||||
interface J extends I {}
|
||||
|
||||
class C implements I, J {
|
||||
{
|
||||
<error descr="Bad type qualifier in default super call: redundant interface I is extended by J">I</error>.super.m();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
class Main<T> {
|
||||
|
||||
{
|
||||
I<Main<String> > aNew = Main[]::new;
|
||||
I<Main<?> > aNew1 = Main<?>[]::new;
|
||||
I<Main<? extends String>> aNew2 = <error descr="Generic array creation">Main<? extends String>[]</error>::new;
|
||||
|
||||
I<int[]> p = int[][]::new;
|
||||
I<Main<String>[]> a = Main[][]::new;
|
||||
I<Main<?>[]> a1 = Main<?>[][]::new;
|
||||
I<Main<? extends String>[]> a2 = <error descr="Generic array creation">Main<? extends String>[][]</error>::new;
|
||||
|
||||
I<Inner<String>> inn1 = Main.Inner[]::new;
|
||||
I<Main<?>.Inner<?>> inn2 = Main<?>.Inner<?>[]::new;
|
||||
I<Main<String>.Inner<String>> inn3 = <error descr="Generic array creation">Main<String>.Inner<String>[]</error>::new;
|
||||
}
|
||||
|
||||
class Inner<P> {}
|
||||
|
||||
interface I<K> {
|
||||
K[] v(int i);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
abstract class Test {
|
||||
void p(final Stream<List<Integer>> stream){
|
||||
stream.flatMap(Collection::<String>stream);
|
||||
stream.flatMap(Collection::<<error descr="Unexpected wildcard">? extends String</error>>stream);
|
||||
stream.flatMap(Collection::<<error descr="Unexpected wildcard">?</error>>stream);
|
||||
stream.flatMap(Collection::<<error descr="Unexpected wildcard">? super String</error>>stream);
|
||||
}
|
||||
|
||||
static <T> void foo(T t) {}
|
||||
interface I {
|
||||
void m(String s);
|
||||
}
|
||||
|
||||
{
|
||||
I i = Test::<String>foo;
|
||||
I i1 = Test::<Integer><error descr="Cannot resolve method 'foo'">foo</error>;
|
||||
I i2 = Test::foo;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import java.util.concurrent.Callable;
|
||||
class Test<T> {
|
||||
|
||||
public <P> Test() {
|
||||
}
|
||||
|
||||
{
|
||||
Callable<Test<String>> c = <error descr="Bad return type in method reference: cannot convert Test to Test<java.lang.String>">Test::<String>new</error>;
|
||||
Callable<Test<String>> c1 = Test<String>::<String>new;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
class Main {
|
||||
public static void main(String[] args) {
|
||||
Stream<List<? extends Main>> listStream = new ArrayList<List<? extends Main>>().stream();
|
||||
Stream<? extends Main> l1 = listStream.flatMap(Collection::stream);
|
||||
Stream<? extends Main> l2 = listStream.flatMap(List::stream);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
interface I {
|
||||
default void a() {}
|
||||
}
|
||||
|
||||
interface J extends I {}
|
||||
|
||||
class A implements I {}
|
||||
class B extends A {}
|
||||
class C implements J {}
|
||||
|
||||
class Test1 implements I { { Runnable r = I.super::a; } }
|
||||
class Test2 implements J { { Runnable r = <error descr="'I' is not an enclosing class">I.super</error>::a; } }
|
||||
class Test3 implements I, J { { Runnable r = <error descr="Bad type qualifier in default super call: redundant interface I is extended by J">I</error>.super::a; } }
|
||||
class Test5 extends A implements I { { Runnable r = I.super::a; } }
|
||||
class Test6 extends A implements J { { Runnable r = <error descr="'I' is not an enclosing class">I.super</error>::a; } }
|
||||
class Test7 extends B { { Runnable r = <error descr="'I' is not an enclosing class">I.super</error>::a; } }
|
||||
class Test8 extends C { { Runnable r = <error descr="'I' is not an enclosing class">I.super</error>::a; } }
|
||||
|
||||
class Test {
|
||||
{
|
||||
class LocalJ implements I {
|
||||
}
|
||||
class Test3 extends LocalJ implements I {
|
||||
{
|
||||
Runnable r = I.super::a;
|
||||
}
|
||||
}
|
||||
|
||||
new I() {
|
||||
{
|
||||
Runnable r = I.super::a;
|
||||
}
|
||||
};
|
||||
|
||||
new A() {
|
||||
{
|
||||
Runnable r = <error descr="'I' is not an enclosing class">I.super</error>::a;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
interface I1 {
|
||||
int i1(int i);
|
||||
}
|
||||
|
||||
interface I2 {
|
||||
Integer i2(Integer i);
|
||||
}
|
||||
|
||||
interface I3 {
|
||||
Integer i3(int i);
|
||||
}
|
||||
|
||||
class Test {
|
||||
|
||||
private void <warning descr="Private method 'm(I1)' is never used">m</warning>(I1 i1) {System.out.println(i1);}
|
||||
private void <warning descr="Private method 'm(I2)' is never used">m</warning>(I2 i2) {System.out.println(i2);}
|
||||
|
||||
private void m1(I1 i1) {System.out.println(i1);}
|
||||
private void <warning descr="Private method 'm1(I3)' is never used">m1</warning>(I3 i2) {System.out.println(i2);}
|
||||
|
||||
void test() {
|
||||
m <error descr="Ambiguous method call: both 'Test.m(I1)' and 'Test.m(I2)' match">(this::bar)</error>;
|
||||
m1(this::bar);
|
||||
}
|
||||
|
||||
int bar(int i) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
class Test {
|
||||
interface GetInt { int get(); }
|
||||
interface GetInteger { Integer get(); }
|
||||
|
||||
private void <warning descr="Private method 'm(Test.GetInt)' is never used">m</warning>(GetInt getter) {
|
||||
System.out.println(getter);
|
||||
}
|
||||
|
||||
private void m(GetInteger getter) {
|
||||
System.out.println(getter);
|
||||
}
|
||||
|
||||
void test(boolean cond) {
|
||||
m<error descr="Cannot resolve method 'm(<lambda expression>)'">(() -> {
|
||||
if (cond)
|
||||
return 42;
|
||||
else
|
||||
return foo();
|
||||
})</error>;
|
||||
|
||||
m(() -> {
|
||||
return foo();
|
||||
});
|
||||
|
||||
m(() -> {
|
||||
if (cond)
|
||||
return new Integer(42);
|
||||
else
|
||||
return foo();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private <T> T foo() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
interface I {
|
||||
void g();
|
||||
|
||||
}
|
||||
interface J {
|
||||
<<warning descr="Type parameter 'T' is never used">T</warning>> void f();
|
||||
}
|
||||
class Test {
|
||||
void m(I i) {System.out.println(i);}
|
||||
void m(J j) {System.out.println(j);}
|
||||
|
||||
void m2(J j){System.out.println(j);}
|
||||
|
||||
{
|
||||
m (() -> {});
|
||||
m2(<error descr="Target method is generic">() -> {}</error>);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class BrokenAlignment {
|
||||
|
||||
{
|
||||
Runnable t = <warning descr="Dereference of 'getString()' may produce 'java.lang.NullPointerException'">getString()</warning>::length;
|
||||
Runnable t2 = BrokenAlignment::getStringStatic;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String getString() {
|
||||
return null;
|
||||
}
|
||||
@Nullable
|
||||
private static String getStringStatic() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import org.jetbrains.annotations.*;
|
||||
|
||||
class Test {
|
||||
@NotNull
|
||||
public static int[] add(@Nullable final int[] ints, final int from, final int to) {
|
||||
if (ints == null || ints.length == 0)
|
||||
return new int[]{from, to};
|
||||
|
||||
for (int i = 0, j = 1; j < ints.length; i+=2, j+=2) {
|
||||
final int intStart = ints[i];
|
||||
final int intFinish = ints[j];
|
||||
|
||||
//check contained
|
||||
if (intStart <= from && to <= intFinish)
|
||||
return ints;
|
||||
|
||||
//try expand 'to' bound
|
||||
if (intStart <= from && from <= intFinish) {
|
||||
ints[j] = to;
|
||||
return ints;
|
||||
}
|
||||
|
||||
//try expand 'from' bound
|
||||
if (intStart <= to && to <= intFinish) {
|
||||
ints[i] = from;
|
||||
return ints;
|
||||
}
|
||||
|
||||
//if we add an interval that contains ors interval
|
||||
//may produce duplicates
|
||||
if (from <= intStart && intFinish <= to) {
|
||||
ints[i] = from;
|
||||
ints[j] = to;
|
||||
return ints;
|
||||
}
|
||||
|
||||
if (from == intFinish + 1) {
|
||||
ints[j] = to;
|
||||
return ints;
|
||||
}
|
||||
if (to == intStart - 1) {
|
||||
ints[i] = from;
|
||||
return ints;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: insert interval sorted?
|
||||
final int[] newInts = new int[ints.length + 2];
|
||||
System.arraycopy(ints, 0, newInts, 0, ints.length);
|
||||
newInts[ints.length] = from;
|
||||
newInts[ints.length+1] = to;
|
||||
return newInts;
|
||||
}}
|
||||
@@ -2,7 +2,7 @@ class A {
|
||||
boolean foo() {
|
||||
|
||||
Inner inner = new Inner().invoke();
|
||||
if (inner.is()) return inner.getFoo();
|
||||
if (inner.is()) return inner.isFoo();
|
||||
|
||||
|
||||
return false;
|
||||
@@ -16,7 +16,7 @@ class A {
|
||||
return myResult;
|
||||
}
|
||||
|
||||
public Boolean getFoo() {
|
||||
public Boolean isFoo() {
|
||||
return foo;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import com.intellij.ide.highlighter.JavaFileType;
|
||||
import com.intellij.lang.LanguageParserDefinitions;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiLanguageInjectionHost;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import com.intellij.testFramework.PsiTestUtil;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.intellij.lang.regexp.RegExpLanguage;
|
||||
import org.intellij.lang.regexp.RegExpParserDefinition;
|
||||
import org.intellij.lang.regexp.intention.CheckRegExpForm;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class JavaCheckRegexpWithFlagsTest extends CodeInsightTestCase {
|
||||
|
||||
private static String getJavaText(@NotNull String regExp, int flags) {
|
||||
return "import java.util.regex.Pattern;\n" +
|
||||
"\n" +
|
||||
"public class Test {\n" +
|
||||
" public void foo() {\n" +
|
||||
" Pattern.compile(\"<caret>" + regExp + "\", " + flags + ");\n" +
|
||||
" }\n" +
|
||||
"}\n";
|
||||
}
|
||||
|
||||
private void defaultTest(@NotNull String regExp, int flags, @NotNull String[] matching, @NotNull String[] nonMatching) throws Exception {
|
||||
LanguageParserDefinitions.INSTANCE.addExplicitExtension(RegExpLanguage.INSTANCE,
|
||||
new RegExpParserDefinition());
|
||||
|
||||
// the 1.8 mock jdk has the needed Pattern class
|
||||
PsiTestUtil.removeAllRoots(myModule, IdeaTestUtil.getMockJdk18());
|
||||
|
||||
configureByText(JavaFileType.INSTANCE, getJavaText(regExp, flags));
|
||||
final PsiFile regexpFile = setUpRegexpInjectionAndGetRegexpFile();
|
||||
|
||||
for (String text : matching) {
|
||||
assertTrue("Text '" + text + "' should match", CheckRegExpForm.isMatchingTextTest(regexpFile, text));
|
||||
}
|
||||
for (String text : nonMatching) {
|
||||
assertFalse("Text '" + text + "' should not match", CheckRegExpForm.isMatchingTextTest(regexpFile, text));
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private PsiFile setUpRegexpInjectionAndGetRegexpFile() {
|
||||
final PsiFile file = getFile();
|
||||
|
||||
int offsetWithRegexp = file.getText().indexOf("Pattern.compile(\"")
|
||||
+ "Pattern.compile(\"".length();
|
||||
|
||||
final PsiElement stringLiteralLeaf = file.findElementAt(offsetWithRegexp);
|
||||
assertNotNull(stringLiteralLeaf);
|
||||
assertNotNull(stringLiteralLeaf.getParent());
|
||||
assertTrue(stringLiteralLeaf.getParent() instanceof PsiLanguageInjectionHost);
|
||||
|
||||
final PsiLanguageInjectionHost elementWithInjection = ((PsiLanguageInjectionHost)stringLiteralLeaf.getParent());
|
||||
|
||||
InjectedLanguageUtil.enumerate(elementWithInjection, file, false, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
@Override
|
||||
public void visit(@NotNull final PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue(InjectedLanguageUtil.hasInjections(elementWithInjection));
|
||||
final PsiElement elementInInjected =
|
||||
InjectedLanguageUtil.findElementInInjected(elementWithInjection, offsetWithRegexp);
|
||||
|
||||
final PsiFile regexpFile = PsiTreeUtil.getParentOfType(elementInInjected, PsiFile.class);
|
||||
assertNotNull(regexpFile);
|
||||
|
||||
return regexpFile;
|
||||
}
|
||||
|
||||
public void testSimple() throws Exception {
|
||||
defaultTest("abc|def|xy.", 0, new String[]{"abc", "def", "xyz"}, new String[]{"", "abcd", "Abc", "xy\n"});
|
||||
}
|
||||
|
||||
public void testEnsureFlagsParameterIsUsed() throws Exception {
|
||||
defaultTest("abc|def|xy.", Pattern.DOTALL, new String[]{"xyz", "xy\n"}, ArrayUtil.EMPTY_STRING_ARRAY);
|
||||
}
|
||||
|
||||
public void testEnsureJavaNotRubyModeIsEnabled() throws Exception {
|
||||
defaultTest("(?ms:^abc$.*)|(?m:xy.)", 0, new String[]{"abc", "abc\na", "xyz"}, new String[]{"xy\n"});
|
||||
}
|
||||
}
|
||||
@@ -788,6 +788,10 @@ public class GenericsHighlighting8Test extends LightDaemonAnalyzerTestCase {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
public void testSuperInterfaceMethodCalledByMatterOfInterface() throws Exception {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
@@ -80,6 +80,7 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
public void testLiftedIntersectionType() { doTest(); }
|
||||
public void testInferenceFromReturnStatements() { doTest(); }
|
||||
public void testDownUpThroughLambdaReturnStatements() { doTest(); }
|
||||
@Bombed(year = 2015, month = Calendar.MARCH, day = 30)
|
||||
public void testIDEA124547() { doTest(); }
|
||||
public void testIDEA118362() { doTest(); }
|
||||
public void testIDEA126056() { doTest(); }
|
||||
@@ -162,6 +163,7 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@Bombed(year = 2015, month = Calendar.MARCH, day = 30)
|
||||
public void testIDEA127124() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
@@ -342,6 +342,26 @@ public class NewMethodRefHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testRawReferenceTypeWithReceiver() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testMethodReferenceTypeArgumentsApplicability() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testTypeNameInterfaceSuperMethodReferenceApplicability() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testNewParameterizedReferenceOnRawType() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testArrayTypeNewReifiable() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
@@ -67,6 +67,18 @@ public class OverloadResolutionTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testLambdaIsNotCongruentWithFunctionalTypeWithTypeParams() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testDetectPolyExpressionInReturnsOfExplicitlyTypedLambdaWhenPrimitiveCouldWin() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testDetectNotEqualParametersInFunctionalTypesForExactMethodReferences() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(true);
|
||||
}
|
||||
|
||||
@@ -76,6 +76,8 @@ public class DataFlowInspection8Test extends LightCodeInsightFixtureTestCase {
|
||||
});
|
||||
}
|
||||
|
||||
public void testMethodReferenceOnNullable() { doTest(); }
|
||||
|
||||
public void testNullableForeachVariable() {
|
||||
setupCustomAnnotations();
|
||||
doTest();
|
||||
|
||||
@@ -282,6 +282,8 @@ public class DataFlowInspectionTest extends LightCodeInsightFixtureTestCase {
|
||||
public void testNumberComparisonsWhenValueIsKnown() { doTest(); }
|
||||
public void testFloatComparisons() { doTest(); }
|
||||
|
||||
public void testNullableArray() { doTest(); }
|
||||
|
||||
public void testAccessingSameArrayElements() { doTest(); }
|
||||
|
||||
public void testParametersAreNonnullByDefault() {
|
||||
|
||||
@@ -16,22 +16,26 @@
|
||||
package com.intellij.ide.util.projectWizard;
|
||||
|
||||
|
||||
import com.intellij.openapi.module.ModifiableModuleModel;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleType;
|
||||
import com.intellij.openapi.module.StdModuleTypes;
|
||||
import com.intellij.openapi.options.ConfigurationException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.project.ProjectManager;
|
||||
import com.intellij.openapi.projectRoots.JavaSdkType;
|
||||
import com.intellij.openapi.projectRoots.SdkTypeId;
|
||||
import com.intellij.openapi.roots.CompilerModuleExtension;
|
||||
import com.intellij.openapi.roots.ContentEntry;
|
||||
import com.intellij.openapi.roots.ModifiableRootModel;
|
||||
import com.intellij.openapi.roots.OrderRootType;
|
||||
import com.intellij.openapi.roots.*;
|
||||
import com.intellij.openapi.roots.libraries.Library;
|
||||
import com.intellij.openapi.roots.libraries.LibraryTable;
|
||||
import com.intellij.openapi.roots.ui.configuration.ModulesProvider;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VfsUtilCore;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -128,7 +132,7 @@ public class JavaModuleBuilder extends ModuleBuilder implements SourcePathsBuild
|
||||
canonicalPath = myCompilerOutputPath;
|
||||
}
|
||||
compilerModuleExtension
|
||||
.setCompilerOutputPath(VfsUtil.pathToUrl(FileUtil.toSystemIndependentName(canonicalPath)));
|
||||
.setCompilerOutputPath(VfsUtilCore.pathToUrl(FileUtil.toSystemIndependentName(canonicalPath)));
|
||||
}
|
||||
else {
|
||||
compilerModuleExtension.inheritCompilerOutputPath(true);
|
||||
@@ -148,6 +152,14 @@ public class JavaModuleBuilder extends ModuleBuilder implements SourcePathsBuild
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public List<Module> commit(@NotNull Project project, ModifiableModuleModel model, ModulesProvider modulesProvider) {
|
||||
LanguageLevel defaultLevel = LanguageLevelProjectExtension.getInstance(ProjectManager.getInstance().getDefaultProject()).getLanguageLevel();
|
||||
LanguageLevelProjectExtension.getInstance(project).setLanguageLevel(defaultLevel);
|
||||
return super.commit(project, model, modulesProvider);
|
||||
}
|
||||
|
||||
private static String getUrlByPath(final String path) {
|
||||
return VfsUtil.getUrlForLibraryRoot(new File(path));
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ src/b.p
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/m/PackageFacade.class
|
||||
out/production/m/a.class
|
||||
out/production/m/xxx/PackageFacade.class
|
||||
out/production/m/xxx/b.class
|
||||
End of files
|
||||
|
||||
@@ -4,6 +4,7 @@ out/production/m/b.class
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/m/PackageFacade.class
|
||||
out/production/m/a.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/a.p
|
||||
|
||||
@@ -15,19 +15,25 @@
|
||||
*/
|
||||
package org.jetbrains.jps.builders;
|
||||
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import gnu.trove.TIntHashSet;
|
||||
import gnu.trove.TIntObjectHashMap;
|
||||
import gnu.trove.TIntProcedure;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.builders.storage.SourceToOutputMapping;
|
||||
import org.jetbrains.jps.cmdline.ProjectDescriptor;
|
||||
import org.jetbrains.jps.incremental.MessageHandler;
|
||||
import org.jetbrains.jps.incremental.messages.BuildMessage;
|
||||
import org.jetbrains.jps.incremental.messages.DoneSomethingNotification;
|
||||
import org.jetbrains.jps.incremental.storage.OutputToTargetRegistry;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
@@ -53,6 +59,7 @@ public class BuildResult implements MessageHandler {
|
||||
final PrintStream stream = new PrintStream(dump);
|
||||
try {
|
||||
pd.dataManager.getMappings().toStream(stream);
|
||||
dumpSourceToOutputMappings(pd, stream);
|
||||
}
|
||||
finally {
|
||||
stream.close();
|
||||
@@ -62,6 +69,63 @@ public class BuildResult implements MessageHandler {
|
||||
myMappingsDump = dump.toString();
|
||||
}
|
||||
|
||||
private static void dumpSourceToOutputMappings(ProjectDescriptor pd, PrintStream stream) throws IOException {
|
||||
List<BuildTarget<?>> targets = new ArrayList<BuildTarget<?>>(pd.getBuildTargetIndex().getAllTargets());
|
||||
Collections.sort(targets, new Comparator<BuildTarget<?>>() {
|
||||
@Override
|
||||
public int compare(BuildTarget<?> o1, BuildTarget<?> o2) {
|
||||
return StringUtil.comparePairs(o1.getTargetType().getTypeId(), o1.getId(), o2.getTargetType().getTypeId(), o2.getId(), false);
|
||||
}
|
||||
});
|
||||
final TIntObjectHashMap<BuildTarget<?>> id2Target = new TIntObjectHashMap<BuildTarget<?>>();
|
||||
for (BuildTarget<?> target : targets) {
|
||||
id2Target.put(pd.dataManager.getTargetsState().getBuildTargetId(target), target);
|
||||
}
|
||||
TIntObjectHashMap<String> hashCodeToOutputPath = new TIntObjectHashMap<String>();
|
||||
for (BuildTarget<?> target : targets) {
|
||||
stream.println("Begin Of SourceToOutput (target " + getTargetIdWithTypeId(target) + ")");
|
||||
SourceToOutputMapping map = pd.dataManager.getSourceToOutputMap(target);
|
||||
List<String> sourcesList = new ArrayList<String>(map.getSources());
|
||||
Collections.sort(sourcesList);
|
||||
for (String source : sourcesList) {
|
||||
List<String> outputs = new ArrayList<String>(ObjectUtils.notNull(map.getOutputs(source), Collections.<String>emptySet()));
|
||||
Collections.sort(outputs);
|
||||
for (String output : outputs) {
|
||||
hashCodeToOutputPath.put(FileUtil.pathHashCode(output), output);
|
||||
}
|
||||
stream.println(" " + source + " -> " + StringUtil.join(outputs, ","));
|
||||
}
|
||||
stream.println("End Of SourceToOutput (target " + getTargetIdWithTypeId(target) + ")");
|
||||
}
|
||||
|
||||
|
||||
OutputToTargetRegistry registry = pd.dataManager.getOutputToTargetRegistry();
|
||||
List<Integer> keys = new ArrayList<Integer>(registry.getKeys());
|
||||
Collections.sort(keys);
|
||||
stream.println("Begin Of OutputToTarget");
|
||||
for (Integer key : keys) {
|
||||
TIntHashSet targetsIds = registry.getState(key);
|
||||
if (targetsIds == null) continue;
|
||||
final List<String> targetsNames = new ArrayList<String>();
|
||||
targetsIds.forEach(new TIntProcedure() {
|
||||
@Override
|
||||
public boolean execute(int value) {
|
||||
BuildTarget<?> target = id2Target.get(value);
|
||||
targetsNames.add(target != null ? getTargetIdWithTypeId(target) : "<unknown " + value + ">");
|
||||
return true;
|
||||
}
|
||||
});
|
||||
Collections.sort(targetsNames);
|
||||
stream.println(hashCodeToOutputPath.get(key) + " -> " + targetsNames);
|
||||
}
|
||||
stream.println("End Of OutputToTarget");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getTargetIdWithTypeId(BuildTarget<?> target) {
|
||||
return target.getTargetType().getTypeId() + ":" + target.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processMessage(BuildMessage msg) {
|
||||
if (msg.getKind() == BuildMessage.Kind.ERROR) {
|
||||
|
||||
@@ -72,7 +72,8 @@ class MockPackageFacadeGenerator : ModuleLevelBuilder(BuilderCategory.SOURCE_PRO
|
||||
val mappings = context.getProjectDescriptor().dataManager.getMappings()
|
||||
val callback = JavaBuilderUtil.getDependenciesRegistrar(context)
|
||||
|
||||
fun generateClass(packageName: String, className: String, target: ModuleBuildTarget, sources: Collection<String>, generate: (ClassWriter.() -> Unit)? = null) {
|
||||
fun generateClass(packageName: String, className: String, target: ModuleBuildTarget, sources: Collection<String>,
|
||||
allSources: Collection<String>, generate: (ClassWriter.() -> Unit)? = null) {
|
||||
val writer = ClassWriter(ClassWriter.COMPUTE_FRAMES)
|
||||
val fullClassName = StringUtil.getQualifiedName(packageName, className).replace('.', '/')
|
||||
writer.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC, fullClassName, null, "java/lang/Object", null)
|
||||
@@ -84,39 +85,53 @@ class MockPackageFacadeGenerator : ModuleLevelBuilder(BuilderCategory.SOURCE_PRO
|
||||
val classBytes = writer.toByteArray()
|
||||
FileUtil.writeToFile(outputFile, classBytes)
|
||||
outputConsumer.registerOutputFile(target, outputFile, sources)
|
||||
callback.associate(fullClassName.replace('/', '.'), sources, ClassReader(classBytes))
|
||||
callback.associate(fullClassName.replace('/', '.'), allSources, ClassReader(classBytes))
|
||||
}
|
||||
|
||||
for (target in chunk.getTargets()) {
|
||||
val packagesStorage = context.getProjectDescriptor().dataManager.getStorage(target, PACKAGE_CACHE_STORAGE_PROVIDER)
|
||||
for (file in filesToCompile[target]) {
|
||||
generateClass(getPackageName(file), FileUtil.getNameWithoutExtension(file), target, listOf(file.getAbsolutePath()))
|
||||
val sources = listOf(file.getAbsolutePath())
|
||||
generateClass(getPackageName(file), FileUtil.getNameWithoutExtension(file), target, sources, sources)
|
||||
}
|
||||
|
||||
val packagesToGenerate = filesToCompile[target].mapTo(THashSet<String>(), ::getPackageName)
|
||||
filesToCompile[target].mapNotNullTo(packagesToGenerate) { packagesStorage.getState(it.getAbsolutePath()) }
|
||||
val packagesToGenerate = LinkedHashMap<String, MutableList<File>>()
|
||||
filesToCompile[target].forEach {
|
||||
val currentName = getPackageName(it)
|
||||
if (currentName !in packagesToGenerate) packagesToGenerate[currentName] = ArrayList()
|
||||
packagesToGenerate[currentName].add(it)
|
||||
val oldName = packagesStorage.getState(it.getAbsolutePath())
|
||||
if (oldName != null && oldName != currentName && oldName !in packagesToGenerate) {
|
||||
packagesToGenerate[oldName] = ArrayList()
|
||||
}
|
||||
}
|
||||
val packagesFromDeletedFiles = dirtyFilesHolder.getRemovedFiles(target).filter { isCompilable(File(it)) }.mapNotNull { packagesStorage.getState(it) }
|
||||
packagesToGenerate.addAll(packagesFromDeletedFiles)
|
||||
packagesFromDeletedFiles.forEach {
|
||||
if (it !in packagesToGenerate) {
|
||||
packagesToGenerate[it] = ArrayList()
|
||||
}
|
||||
}
|
||||
|
||||
val getParentFile: (File) -> File = { it.getParentFile() }
|
||||
val dirsToCheck = filesToCompile[target].mapTo(THashSet(FileUtil.FILE_HASHING_STRATEGY), getParentFile)
|
||||
packagesFromDeletedFiles.flatMap { mappings.getClassSources(mappings.getName(StringUtil.getQualifiedName(it, "PackageFacade"))) }
|
||||
.map(getParentFile).filterNotNullTo(dirsToCheck)
|
||||
|
||||
for (packageName in packagesToGenerate) {
|
||||
for ((packageName, dirtyFiles) in packagesToGenerate) {
|
||||
val files = dirsToCheck.map { it.listFiles() }.filterNotNull().flatMap { it.toList() }.filter { isCompilable(it) && packageName == getPackageName(it) }
|
||||
if (files.isEmpty()) continue
|
||||
|
||||
val classNames = files.map { FileUtilRt.getNameWithoutExtension(it.getName()) }.sort()
|
||||
val sources = files.map { it.getAbsolutePath() }
|
||||
val dirtySource = dirtyFiles.map { it.getAbsolutePath() }
|
||||
val allSources = files.map { it.getAbsolutePath() }
|
||||
|
||||
generateClass(packageName, "PackageFacade", target, sources) {
|
||||
generateClass(packageName, "PackageFacade", target, dirtySource, allSources) {
|
||||
for (fileName in classNames) {
|
||||
val fieldClass = StringUtil.getQualifiedName(packageName, fileName).replace('.', '/')
|
||||
visitField(Opcodes.ACC_PUBLIC, StringUtil.decapitalize(fileName), "L$fieldClass;", null, null).visitEnd()
|
||||
}
|
||||
}
|
||||
for (source in sources) {
|
||||
for (source in dirtySource) {
|
||||
packagesStorage.update(FileUtil.toSystemIndependentName(source), packageName)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.codeHighlighting;
|
||||
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.lang.annotation.HighlightSeverity;
|
||||
import com.intellij.openapi.editor.colors.CodeInsightColors;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
@@ -22,6 +23,7 @@ import com.intellij.openapi.editor.colors.TextAttributesKey;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.util.IconUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.ui.ColorIcon;
|
||||
@@ -38,7 +40,18 @@ public class HighlightDisplayLevel {
|
||||
|
||||
public static final HighlightDisplayLevel GENERIC_SERVER_ERROR_OR_WARNING = new HighlightDisplayLevel(HighlightSeverity.GENERIC_SERVER_ERROR_OR_WARNING,
|
||||
createIconByKey(CodeInsightColors.GENERIC_SERVER_ERROR_OR_WARNING));
|
||||
public static final HighlightDisplayLevel ERROR = new HighlightDisplayLevel(HighlightSeverity.ERROR, createIconByKey(CodeInsightColors.ERRORS_ATTRIBUTES));
|
||||
public static final HighlightDisplayLevel ERROR = new HighlightDisplayLevel(HighlightSeverity.ERROR, createErrorIcon());
|
||||
|
||||
@NotNull
|
||||
private static Icon createErrorIcon() {
|
||||
return new SingleColorIcon(CodeInsightColors.ERRORS_ATTRIBUTES) {
|
||||
@Override
|
||||
public void paintIcon(Component c, Graphics g, int x, int y) {
|
||||
IconUtil.colorize(AllIcons.General.InspectionsError, getColor()).paintIcon(c, g, x, y);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static final HighlightDisplayLevel WARNING = new HighlightDisplayLevel(HighlightSeverity.WARNING, createIconByKey(CodeInsightColors.WARNINGS_ATTRIBUTES));
|
||||
private static final Icon DO_NOT_SHOW_KEY = createIconByKey(TextAttributesKey.createTextAttributesKey("DO_NOT_SHOW"));
|
||||
public static final HighlightDisplayLevel DO_NOT_SHOW = new HighlightDisplayLevel(HighlightSeverity.INFORMATION, DO_NOT_SHOW_KEY);
|
||||
@@ -99,8 +112,8 @@ public class HighlightDisplayLevel {
|
||||
return mySeverity;
|
||||
}
|
||||
|
||||
public static void registerSeverity(@NotNull HighlightSeverity severity, final TextAttributesKey key) {
|
||||
Icon severityIcon = createIconByKey(key);
|
||||
public static void registerSeverity(@NotNull HighlightSeverity severity, @NotNull TextAttributesKey key, @Nullable Icon icon) {
|
||||
Icon severityIcon = icon != null ? icon : createIconByKey(key);
|
||||
final HighlightDisplayLevel level = ourMap.get(severity);
|
||||
if (level == null) {
|
||||
new HighlightDisplayLevel(severity, severityIcon);
|
||||
@@ -111,7 +124,7 @@ public class HighlightDisplayLevel {
|
||||
}
|
||||
|
||||
public static int getEmptyIconDim() {
|
||||
return JBUI.scale(13);
|
||||
return JBUI.scale(14);
|
||||
}
|
||||
|
||||
public static Icon createIconByKey(@NotNull TextAttributesKey key) {
|
||||
@@ -141,7 +154,7 @@ public class HighlightDisplayLevel {
|
||||
public static class SingleColorIcon implements Icon, ColoredIcon {
|
||||
private final TextAttributesKey myKey;
|
||||
|
||||
public SingleColorIcon(final TextAttributesKey key) {
|
||||
public SingleColorIcon(@NotNull TextAttributesKey key) {
|
||||
myKey = key;
|
||||
}
|
||||
|
||||
@@ -165,11 +178,9 @@ public class HighlightDisplayLevel {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void paintIcon(final Component c, final Graphics g, final int x, final int y) {
|
||||
public void paintIcon(Component c, Graphics g, int x, int y) {
|
||||
g.setColor(getColor());
|
||||
g.translate(x, y);
|
||||
g.fillPolygon(new int[]{0, getEmptyIconDim(), getEmptyIconDim()}, new int[]{0, 0, getEmptyIconDim()}, 3);
|
||||
g.translate(-x, -y);
|
||||
g.fillRect(x + 2, y + 2, 10, 10);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.ThreeState;
|
||||
|
||||
/**
|
||||
* This kind of suppression fix allows to clients to specify whether the fix should
|
||||
* be invoked on injected elements or on elements of host files.
|
||||
* <p/>
|
||||
* By default suppression fixes on injected elements are able to make suppression inside injection only.
|
||||
* Whereas implementation of this interface will be provided for suppressing inside injection and in injection host.
|
||||
* See {@link InspectionProfileEntry#getBatchSuppressActions(PsiElement)} for details.
|
||||
*/
|
||||
public interface InjectionAwareSuppressQuickFix extends SuppressQuickFix {
|
||||
ThreeState isShouldBeAppliedToInjectionHost();
|
||||
|
||||
void setShouldBeAppliedToInjectionHost(ThreeState shouldBeAppliedToInjectionHost);
|
||||
}
|
||||
@@ -17,6 +17,7 @@ package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.codeHighlighting.HighlightDisplayLevel;
|
||||
import com.intellij.lang.Language;
|
||||
import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.InvalidDataException;
|
||||
@@ -24,8 +25,10 @@ import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.FileViewProvider;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiLanguageInjectionHost;
|
||||
import com.intellij.psi.templateLanguages.TemplateLanguageFileViewProvider;
|
||||
import com.intellij.util.ResourceUtil;
|
||||
import com.intellij.util.ThreeState;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.xmlb.SerializationFilter;
|
||||
import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
|
||||
@@ -44,14 +47,16 @@ import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author anna
|
||||
* @since 28-Nov-2005
|
||||
*/
|
||||
@SuppressWarnings("JavadocReference")
|
||||
public abstract class InspectionProfileEntry implements BatchSuppressableTool{
|
||||
public abstract class InspectionProfileEntry implements BatchSuppressableTool {
|
||||
public static final String GENERAL_GROUP_NAME = InspectionsBundle.message("inspection.general.tools.group.name");
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInspection.InspectionProfileEntry");
|
||||
@@ -93,22 +98,52 @@ public abstract class InspectionProfileEntry implements BatchSuppressableTool{
|
||||
Set<SuppressQuickFix> fixes = new THashSet<SuppressQuickFix>(new TObjectHashingStrategy<SuppressQuickFix>() {
|
||||
@Override
|
||||
public int computeHashCode(SuppressQuickFix object) {
|
||||
return object.getName().hashCode();
|
||||
int result = object instanceof InjectionAwareSuppressQuickFix
|
||||
? ((InjectionAwareSuppressQuickFix)object).isShouldBeAppliedToInjectionHost().hashCode()
|
||||
: 0;
|
||||
return 31 * result + object.getName().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(SuppressQuickFix o1, SuppressQuickFix o2) {
|
||||
if (o1 instanceof InjectionAwareSuppressQuickFix && o2 instanceof InjectionAwareSuppressQuickFix) {
|
||||
if (((InjectionAwareSuppressQuickFix)o1).isShouldBeAppliedToInjectionHost() != ((InjectionAwareSuppressQuickFix)o2).isShouldBeAppliedToInjectionHost()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return o1.getName().equals(o2.getName());
|
||||
}
|
||||
});
|
||||
|
||||
Set<InspectionSuppressor> suppressors = getSuppressors(element);
|
||||
final PsiLanguageInjectionHost injectionHost = InjectedLanguageManager.getInstance(element.getProject()).getInjectionHost(element);
|
||||
if (injectionHost != null) {
|
||||
Set<InspectionSuppressor> injectionHostSuppressors = getSuppressors(injectionHost);
|
||||
for (InspectionSuppressor suppressor : injectionHostSuppressors) {
|
||||
addAllSuppressActions(fixes, injectionHost, suppressor, ThreeState.YES, getShortName());
|
||||
}
|
||||
}
|
||||
|
||||
for (InspectionSuppressor suppressor : suppressors) {
|
||||
SuppressQuickFix[] actions = suppressor.getSuppressActions(element, getShortName());
|
||||
fixes.addAll(Arrays.asList(actions));
|
||||
addAllSuppressActions(fixes, element, suppressor, injectionHost != null ? ThreeState.NO : ThreeState.UNSURE, getShortName());
|
||||
}
|
||||
return fixes.toArray(new SuppressQuickFix[fixes.size()]);
|
||||
}
|
||||
|
||||
private static void addAllSuppressActions(Set<SuppressQuickFix> fixes,
|
||||
PsiElement element,
|
||||
InspectionSuppressor suppressor,
|
||||
ThreeState appliedToInjectionHost,
|
||||
String toolShortName) {
|
||||
final SuppressQuickFix[] actions = suppressor.getSuppressActions(element, toolShortName);
|
||||
for (SuppressQuickFix action : actions) {
|
||||
if (action instanceof InjectionAwareSuppressQuickFix) {
|
||||
((InjectionAwareSuppressQuickFix)action).setShouldBeAppliedToInjectionHost(appliedToInjectionHost);
|
||||
}
|
||||
fixes.add(action);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSuppressed(@NotNull String toolId,
|
||||
@NotNull InspectionSuppressor suppressor,
|
||||
@NotNull PsiElement element) {
|
||||
@@ -132,7 +167,9 @@ public abstract class InspectionProfileEntry implements BatchSuppressableTool{
|
||||
ContainerUtil.addIfNotNull(suppressors, elementLanguageSuppressor);
|
||||
return suppressors;
|
||||
}
|
||||
return elementLanguageSuppressor != null ? Collections.singleton(elementLanguageSuppressor) : Collections.<InspectionSuppressor>emptySet();
|
||||
return elementLanguageSuppressor != null
|
||||
? Collections.singleton(elementLanguageSuppressor)
|
||||
: Collections.<InspectionSuppressor>emptySet();
|
||||
}
|
||||
|
||||
public void cleanup(Project project) {
|
||||
@@ -148,9 +185,9 @@ public abstract class InspectionProfileEntry implements BatchSuppressableTool{
|
||||
protected volatile DefaultNameProvider myNameProvider = null;
|
||||
|
||||
/**
|
||||
* @see com.intellij.codeInspection.InspectionEP#groupDisplayName
|
||||
* @see com.intellij.codeInspection.InspectionEP#groupKey
|
||||
* @see com.intellij.codeInspection.InspectionEP#groupBundle
|
||||
* @see InspectionEP#groupDisplayName
|
||||
* @see InspectionEP#groupKey
|
||||
* @see InspectionEP#groupBundle
|
||||
*/
|
||||
@Nls
|
||||
@NotNull
|
||||
@@ -166,7 +203,7 @@ public abstract class InspectionProfileEntry implements BatchSuppressableTool{
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.intellij.codeInspection.InspectionEP#groupPath
|
||||
* @see InspectionEP#groupPath
|
||||
*/
|
||||
@NotNull
|
||||
public String[] getGroupPath() {
|
||||
@@ -178,9 +215,9 @@ public abstract class InspectionProfileEntry implements BatchSuppressableTool{
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.intellij.codeInspection.InspectionEP#displayName
|
||||
* @see com.intellij.codeInspection.InspectionEP#key
|
||||
* @see com.intellij.codeInspection.InspectionEP#bundle
|
||||
* @see InspectionEP#displayName
|
||||
* @see InspectionEP#key
|
||||
* @see InspectionEP#bundle
|
||||
*/
|
||||
@Nls
|
||||
@NotNull
|
||||
@@ -198,7 +235,7 @@ public abstract class InspectionProfileEntry implements BatchSuppressableTool{
|
||||
/**
|
||||
* DO NOT OVERRIDE this method.
|
||||
*
|
||||
* @see com.intellij.codeInspection.InspectionEP#shortName
|
||||
* @see InspectionEP#shortName
|
||||
*/
|
||||
@NonNls
|
||||
@NotNull
|
||||
@@ -214,13 +251,13 @@ public abstract class InspectionProfileEntry implements BatchSuppressableTool{
|
||||
|
||||
@NotNull
|
||||
public static String getShortName(@NotNull String className) {
|
||||
return StringUtil.trimEnd(StringUtil.trimEnd(className, "Inspection"),"InspectionBase");
|
||||
return StringUtil.trimEnd(StringUtil.trimEnd(className, "Inspection"), "InspectionBase");
|
||||
}
|
||||
|
||||
/**
|
||||
* DO NOT OVERRIDE this method.
|
||||
*
|
||||
* @see com.intellij.codeInspection.InspectionEP#level
|
||||
* @see InspectionEP#level
|
||||
*/
|
||||
@NotNull
|
||||
public HighlightDisplayLevel getDefaultLevel() {
|
||||
@@ -230,7 +267,7 @@ public abstract class InspectionProfileEntry implements BatchSuppressableTool{
|
||||
/**
|
||||
* DO NOT OVERRIDE this method.
|
||||
*
|
||||
* @see com.intellij.codeInspection.InspectionEP#enabledByDefault
|
||||
* @see InspectionEP#enabledByDefault
|
||||
*/
|
||||
public boolean isEnabledByDefault() {
|
||||
return false;
|
||||
@@ -238,6 +275,7 @@ public abstract class InspectionProfileEntry implements BatchSuppressableTool{
|
||||
|
||||
/**
|
||||
* This method is called each time UI is shown.
|
||||
*
|
||||
* @return null if no UI options required.
|
||||
*/
|
||||
@Nullable
|
||||
@@ -348,7 +386,7 @@ public abstract class InspectionProfileEntry implements BatchSuppressableTool{
|
||||
* Initialize inspection with project. Is called on project opened for all profiles as well as on profile creation.
|
||||
*
|
||||
* @param project to be associated with this entry
|
||||
* @deprecated this won't work for inspections configured via {@link com.intellij.codeInspection.InspectionEP}
|
||||
* @deprecated this won't work for inspections configured via {@link InspectionEP}
|
||||
*/
|
||||
public void projectOpened(@NotNull Project project) {
|
||||
}
|
||||
@@ -357,7 +395,7 @@ public abstract class InspectionProfileEntry implements BatchSuppressableTool{
|
||||
* Cleanup inspection settings corresponding to the project. Is called on project closed for all profiles as well as on profile deletion.
|
||||
*
|
||||
* @param project to be disassociated from this entry
|
||||
* @deprecated this won't work for inspections configured via {@link com.intellij.codeInspection.InspectionEP}
|
||||
* @deprecated this won't work for inspections configured via {@link InspectionEP}
|
||||
*/
|
||||
public void projectClosed(@NotNull Project project) {
|
||||
}
|
||||
@@ -411,7 +449,8 @@ public abstract class InspectionProfileEntry implements BatchSuppressableTool{
|
||||
if (descriptionUrl == null) return null;
|
||||
return ResourceUtil.loadText(descriptionUrl);
|
||||
}
|
||||
catch (IOException ignored) { }
|
||||
catch (IOException ignored) {
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -36,6 +36,8 @@ import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
|
||||
public interface HighlightInfoType {
|
||||
@NonNls String UNUSED_SYMBOL_SHORT_NAME = "unused";
|
||||
@NonNls String UNUSED_SYMBOL_DISPLAY_NAME = InspectionsBundle.message("inspection.dead.code.display.name");
|
||||
@@ -201,4 +203,8 @@ public interface HighlightInfoType {
|
||||
return myToolKey;
|
||||
}
|
||||
}
|
||||
|
||||
interface Iconable {
|
||||
Icon getIcon();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -27,7 +27,6 @@ import com.intellij.openapi.util.JDOMExternalizableStringList;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.profile.codeInspection.InspectionProfileManager;
|
||||
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.concurrency.AtomicFieldUpdater;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -94,7 +93,7 @@ public class SeverityRegistrar implements JDOMExternalizable, Comparator<Highlig
|
||||
myRendererColors.put(severity.getName(), renderColor);
|
||||
}
|
||||
myOrderMap = null;
|
||||
HighlightDisplayLevel.registerSeverity(severity, getHighlightInfoTypeBySeverity(severity).getAttributesKey());
|
||||
HighlightDisplayLevel.registerSeverity(severity, getHighlightInfoTypeBySeverity(severity).getAttributesKey(), null);
|
||||
severitiesChanged();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,9 +17,9 @@
|
||||
package com.intellij.codeInsight.daemon.impl.actions;
|
||||
|
||||
import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInspection.InjectionAwareSuppressQuickFix;
|
||||
import com.intellij.codeInspection.InspectionsBundle;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.codeInspection.SuppressQuickFix;
|
||||
import com.intellij.codeInspection.SuppressionUtil;
|
||||
import com.intellij.icons.AllIcons;
|
||||
import com.intellij.lang.Language;
|
||||
@@ -32,6 +32,7 @@ import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.PsiWhiteSpace;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.ThreeState;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -43,9 +44,10 @@ import java.util.List;
|
||||
* @author Roman.Chernyatchik
|
||||
* @date Aug 13, 2009
|
||||
*/
|
||||
public abstract class AbstractBatchSuppressByNoInspectionCommentFix implements SuppressQuickFix, Iconable {
|
||||
public abstract class AbstractBatchSuppressByNoInspectionCommentFix implements InjectionAwareSuppressQuickFix, Iconable {
|
||||
@NotNull protected final String myID;
|
||||
private final boolean myReplaceOtherSuppressionIds;
|
||||
private ThreeState myShouldBeAppliedToInjectionHost = ThreeState.UNSURE;
|
||||
|
||||
@Nullable
|
||||
public abstract PsiElement getContainer(final PsiElement context);
|
||||
@@ -60,6 +62,15 @@ public abstract class AbstractBatchSuppressByNoInspectionCommentFix implements S
|
||||
myReplaceOtherSuppressionIds = replaceOtherSuppressionIds;
|
||||
}
|
||||
|
||||
public void setShouldBeAppliedToInjectionHost(ThreeState shouldBeAppliedToInjectionHost) {
|
||||
myShouldBeAppliedToInjectionHost = shouldBeAppliedToInjectionHost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ThreeState isShouldBeAppliedToInjectionHost() {
|
||||
return myShouldBeAppliedToInjectionHost;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.ThreeState;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -59,9 +60,15 @@ public class SuppressIntentionActionFromFix extends SuppressIntentionAction {
|
||||
}
|
||||
}
|
||||
|
||||
public ThreeState isShouldBeAppliedToInjectionHost() {
|
||||
return myFix instanceof InjectionAwareSuppressQuickFix
|
||||
? ((InjectionAwareSuppressQuickFix)myFix).isShouldBeAppliedToInjectionHost()
|
||||
: ThreeState.UNSURE;
|
||||
}
|
||||
|
||||
public PsiElement getContainer(PsiElement element) {
|
||||
return myFix instanceof AbstractBatchSuppressByNoInspectionCommentFix
|
||||
? ((AbstractBatchSuppressByNoInspectionCommentFix )myFix).getContainer(element) : null;
|
||||
? ((AbstractBatchSuppressByNoInspectionCommentFix)myFix).getContainer(element) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -72,7 +79,7 @@ public class SuppressIntentionActionFromFix extends SuppressIntentionAction {
|
||||
@NotNull
|
||||
@Override
|
||||
public String getText() {
|
||||
return myFix.getName();
|
||||
return myFix.getName() + (isShouldBeAppliedToInjectionHost() == ThreeState.NO ? " in injection" : "");
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -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.
|
||||
@@ -408,6 +408,10 @@ public class IconUtil {
|
||||
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Icon colorize(@NotNull final Icon source, @NotNull Color color) {
|
||||
return colorize(source, color, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Icon colorize(@NotNull final Icon source, @NotNull Color color, boolean keepGray) {
|
||||
@@ -427,7 +431,7 @@ public class IconUtil {
|
||||
if (rgba[3] != 0) {
|
||||
Color.RGBtoHSB(rgba[0], rgba[1], rgba[2], hsb);
|
||||
int rgb = Color.HSBtoRGB(base[0], base[1] * (keepGray ? hsb[1] : 1f), base[2] * hsb[2]);
|
||||
img.getRaster().setPixel(x, y, new int[]{(rgb >> 16) & 0xff, (rgb >> 8) & 0xff, rgb & 0xff, rgba[3]});
|
||||
img.getRaster().setPixel(x, y, new int[]{rgb >> 16 & 0xff, rgb >> 8 & 0xff, rgb & 0xff, rgba[3]});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileTypes.InternalFileType;
|
||||
import com.intellij.openapi.progress.ProgressIndicatorProvider;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.FileIndexFacade;
|
||||
@@ -49,7 +48,7 @@ public class PsiManagerImpl extends PsiManagerEx {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.PsiManagerImpl");
|
||||
|
||||
private final Project myProject;
|
||||
private final FileIndexFacade myExcludedFileIndex;
|
||||
private final FileIndexFacade myFileIndex;
|
||||
private final MessageBus myMessageBus;
|
||||
private final PsiModificationTracker myModificationTracker;
|
||||
|
||||
@@ -71,11 +70,11 @@ public class PsiManagerImpl extends PsiManagerEx {
|
||||
public PsiManagerImpl(Project project,
|
||||
FileDocumentManager fileDocumentManager,
|
||||
PsiBuilderFactory psiBuilderFactory,
|
||||
FileIndexFacade excludedFileIndex,
|
||||
FileIndexFacade fileIndex,
|
||||
MessageBus messageBus,
|
||||
PsiModificationTracker modificationTracker) {
|
||||
myProject = project;
|
||||
myExcludedFileIndex = excludedFileIndex;
|
||||
myFileIndex = fileIndex;
|
||||
myMessageBus = messageBus;
|
||||
myModificationTracker = modificationTracker;
|
||||
|
||||
@@ -84,7 +83,7 @@ public class PsiManagerImpl extends PsiManagerEx {
|
||||
|
||||
boolean isProjectDefault = project.isDefault();
|
||||
|
||||
myFileManager = isProjectDefault ? new EmptyFileManager(this) : new FileManagerImpl(this, fileDocumentManager, excludedFileIndex);
|
||||
myFileManager = isProjectDefault ? new EmptyFileManager(this) : new FileManagerImpl(this, fileDocumentManager, fileIndex);
|
||||
|
||||
myTreeChangePreprocessors.add((PsiTreeChangePreprocessor)modificationTracker);
|
||||
Collections.addAll(myTreeChangePreprocessors, Extensions.getExtensions(PsiTreeChangePreprocessor.EP_NAME, myProject));
|
||||
@@ -131,10 +130,9 @@ public class PsiManagerImpl extends PsiManagerEx {
|
||||
virtualFile = ((PsiFileSystemItem)element).getVirtualFile();
|
||||
}
|
||||
if (file != null && file.isPhysical() && virtualFile instanceof LightVirtualFile) return true;
|
||||
if (virtualFile != null && virtualFile.getFileType() instanceof InternalFileType) return true;
|
||||
|
||||
if (virtualFile != null) {
|
||||
return myExcludedFileIndex.isInContent(virtualFile);
|
||||
return myFileIndex.isInContent(virtualFile);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -62,7 +62,10 @@ public class StubTree extends ObjectStubTree<StubElement<?>> {
|
||||
@NotNull
|
||||
@Override
|
||||
public List<StubElement<?>> getPlainListFromAllRoots() {
|
||||
return ContainerUtil.concat(getRoot().getStubRoots(), new Function<PsiFileStub, Collection<? extends StubElement<?>>>() {
|
||||
final PsiFileStub[] roots = getRoot().getStubRoots();
|
||||
if (roots.length == 1) return super.getPlainListFromAllRoots();
|
||||
|
||||
return ContainerUtil.concat(roots, new Function<PsiFileStub, Collection<? extends StubElement<?>>>() {
|
||||
@Override
|
||||
public Collection<? extends StubElement<?>> fun(PsiFileStub stub) {
|
||||
final ObjectStubTree existingTree = stub.getUserData(STUB_TO_TREE_REFERENCE);
|
||||
|
||||
@@ -83,20 +83,20 @@ public class RepositoryNode extends CheckedTreeNode implements EditableTreeNode,
|
||||
repoFixedWidth += checkBoxWidth;
|
||||
if (myCheckBoxHGap > 0) {
|
||||
renderer.append("");
|
||||
renderer.appendFixedTextFragmentWidth(checkBoxWidth + renderer.getIconTextGap() + borderHOffset);
|
||||
renderer.appendTextPadding(checkBoxWidth + renderer.getIconTextGap() + borderHOffset);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (myCheckBoxHGap <= 0) {
|
||||
renderer.append("");
|
||||
renderer.appendFixedTextFragmentWidth(myRepositoryPanel.calculateRendererShiftH(renderer));
|
||||
renderer.appendTextPadding(myRepositoryPanel.calculateRendererShiftH(renderer));
|
||||
}
|
||||
}
|
||||
SimpleTextAttributes repositoryDetailsTextAttributes = PushLogTreeUtil
|
||||
.addTransparencyIfNeeded(SimpleTextAttributes.REGULAR_ATTRIBUTES, isChecked());
|
||||
|
||||
renderer.append(getRepoName(renderer, repoFixedWidth), repositoryDetailsTextAttributes);
|
||||
renderer.appendFixedTextFragmentWidth(repoFixedWidth);
|
||||
renderer.appendTextPadding(repoFixedWidth);
|
||||
renderer.append(myRepositoryPanel.getSourceName(), repositoryDetailsTextAttributes);
|
||||
renderer.append(myRepositoryPanel.getArrow(), repositoryDetailsTextAttributes);
|
||||
PushTargetPanel pushTargetPanel = myRepositoryPanel.getTargetPanel();
|
||||
|
||||
@@ -147,10 +147,10 @@ public class RepositoryWithBranchPanel<T extends PushTarget> extends NonOpaquePa
|
||||
myRepositoryCheckbox.setVisible(true);
|
||||
if (myCheckBoxLoadingIconGapH < 0) {
|
||||
myTextRenderer.append("");
|
||||
myTextRenderer.appendFixedTextFragmentWidth(calculateRendererShiftH(myTextRenderer));
|
||||
myTextRenderer.appendTextPadding(calculateRendererShiftH(myTextRenderer));
|
||||
}
|
||||
myTextRenderer.append(getRepositoryName(), SimpleTextAttributes.GRAY_ATTRIBUTES);
|
||||
myTextRenderer.appendFixedTextFragmentWidth(120);
|
||||
myTextRenderer.appendTextPadding(120);
|
||||
}
|
||||
else {
|
||||
myRepositoryCheckbox.setVisible(false);
|
||||
|
||||
|
After Width: | Height: | Size: 570 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 267 B |
|
Before Width: | Height: | Size: 539 B |
|
Before Width: | Height: | Size: 533 B |
|
Before Width: | Height: | Size: 274 B |
|
After Width: | Height: | Size: 161 B |
|
After Width: | Height: | Size: 334 B |
|
After Width: | Height: | Size: 236 B |
|
After Width: | Height: | Size: 448 B |
|
After Width: | Height: | Size: 204 B |
|
After Width: | Height: | Size: 374 B |
|
Before Width: | Height: | Size: 93 B After Width: | Height: | Size: 92 B |
|
Before Width: | Height: | Size: 104 B After Width: | Height: | Size: 109 B |
|
Before Width: | Height: | Size: 106 B After Width: | Height: | Size: 108 B |
|
Before Width: | Height: | Size: 93 B After Width: | Height: | Size: 91 B |
|
After Width: | Height: | Size: 152 B |
|
After Width: | Height: | Size: 196 B |
|
After Width: | Height: | Size: 245 B |
|
After Width: | Height: | Size: 462 B |