Merge remote-tracking branch 'origin/master'

This commit is contained in:
Vladimir.Orlov
2016-08-26 13:36:43 +03:00
10 changed files with 111 additions and 36 deletions
@@ -53,6 +53,7 @@ import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdk;
import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ProjectRootManager;
@@ -631,7 +632,7 @@ public abstract class DebugProcessImpl extends UserDataHolderBase implements Deb
}
private static boolean versionMatch(@Nullable Sdk sdk, String version) {
if (sdk != null) {
if (sdk != null && sdk.getSdkType() instanceof JavaSdk) {
String versionString = sdk.getVersionString();
return versionString != null && versionString.contains(version);
}
@@ -1620,6 +1620,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
if (!myHolder.hasErrorResults()) myHolder.add(ModuleHighlightUtil.checkFileDuplicates(module, myFile));
if (!myHolder.hasErrorResults()) myHolder.addAll(ModuleHighlightUtil.checkDuplicateRequires(module));
if (!myHolder.hasErrorResults()) myHolder.addAll(ModuleHighlightUtil.checkDuplicateExports(module));
if (!myHolder.hasErrorResults()) myHolder.addAll(ModuleHighlightUtil.checkDuplicateUses(module));
if (!myHolder.hasErrorResults()) myHolder.add(ModuleHighlightUtil.checkFileLocation(module, myFile));
}
@@ -1644,6 +1645,15 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
}
}
@Override
public void visitUsesStatement(PsiUsesStatement statement) {
super.visitUsesStatement(statement);
if (PsiUtil.isLanguageLevel9OrHigher(myFile)) {
PsiJavaCodeReferenceElement ref = statement.getClassReference();
if (!myHolder.hasErrorResults()) myHolder.add(ModuleHighlightUtil.checkServiceReference(ref));
}
}
@Nullable
private HighlightInfo checkFeature(@NotNull PsiElement element, @NotNull Feature feature) {
return HighlightUtil.checkFeature(element, feature, myLanguageLevel, myFile);
@@ -35,17 +35,19 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.search.FilenameIndex;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.graph.Graph;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.PropertyKey;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static com.intellij.codeInsight.daemon.JavaErrorMessages.BUNDLE;
import static com.intellij.psi.PsiJavaModule.MODULE_INFO_FILE;
import static com.intellij.psi.SyntaxTraverser.psiTraverser;
@@ -83,23 +85,10 @@ public class ModuleHighlightUtil {
@NotNull
static List<HighlightInfo> checkDuplicateRequires(@NotNull PsiJavaModule module) {
List<HighlightInfo> results = ContainerUtil.newSmartList();
Set<String> names = ContainerUtil.newHashSet();
for (PsiRequiresStatement statement : psiTraverser().children(module).filter(PsiRequiresStatement.class)) {
PsiJavaModuleReferenceElement ref = statement.getReferenceElement();
if (ref != null) {
String text = ref.getReferenceText();
if (!names.add(text)) {
String message = JavaErrorMessages.message("module.duplicate.requires", text);
HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).description(message).create();
QuickFixAction.registerQuickFixAction(info, new DeleteElementFix(statement));
results.add(info);
}
}
}
return results;
return checkDuplicateRefs(
psiTraverser().children(module).filter(PsiRequiresStatement.class),
st -> Optional.ofNullable(st.getReferenceElement()).map(PsiJavaModuleReferenceElement::getReferenceText).orElse(null),
"module.duplicate.requires");
}
@Nullable
@@ -202,23 +191,51 @@ public class ModuleHighlightUtil {
@NotNull
static List<HighlightInfo> checkDuplicateExports(@NotNull PsiJavaModule module) {
List<HighlightInfo> results = ContainerUtil.newSmartList();
return checkDuplicateRefs(
psiTraverser().children(module).filter(PsiExportsStatement.class),
st -> Optional.ofNullable(st.getPackageReference()).map(ref -> PsiNameHelper.getQualifiedClassName(ref.getText(), true)).orElse(null),
"module.duplicate.export");
}
Set<String> names = ContainerUtil.newHashSet();
for (PsiExportsStatement statement : psiTraverser().children(module).filter(PsiExportsStatement.class)) {
PsiJavaCodeReferenceElement ref = statement.getPackageReference();
if (ref != null) {
String text = PsiNameHelper.getQualifiedClassName(ref.getText(), true);
if (!names.add(text)) {
String message = JavaErrorMessages.message("module.duplicate.export", text);
HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).description(message).create();
QuickFixAction.registerQuickFixAction(info, new DeleteElementFix(statement));
results.add(info);
}
@Nullable
static HighlightInfo checkServiceReference(@Nullable PsiJavaCodeReferenceElement refElement) {
if (refElement != null) {
PsiElement target = refElement.resolve();
if (target instanceof PsiClass && ((PsiClass)target).isEnum()) {
String message = JavaErrorMessages.message("module.service.enum", ((PsiClass)target).getName());
return HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(range(refElement)).description(message).create();
}
}
return results;
return null;
}
@NotNull
static List<HighlightInfo> checkDuplicateUses(@NotNull PsiJavaModule module) {
return checkDuplicateRefs(
psiTraverser().children(module).filter(PsiUsesStatement.class),
st -> Optional.ofNullable(st.getClassReference()).map(ref -> PsiNameHelper.getQualifiedClassName(ref.getText(), true)).orElse(null),
"module.duplicate.uses");
}
private static <T extends PsiElement> List<HighlightInfo> checkDuplicateRefs(Iterable<T> statements,
Function<T, String> ref,
@PropertyKey(resourceBundle = BUNDLE) String key) {
List<HighlightInfo> results = null;
Set<String> names = ContainerUtil.newHashSet();
for (T statement : statements) {
String refText = ref.apply(statement);
if (refText != null && !names.add(refText)) {
String message = JavaErrorMessages.message(key, refText);
HighlightInfo info = HighlightInfo.newHighlightInfo(HighlightInfoType.ERROR).range(statement).description(message).create();
QuickFixAction.registerQuickFixAction(info, new DeleteElementFix(statement));
if (results == null) results = ContainerUtil.newSmartList();
results.add(info);
}
}
return results != null ? results : Collections.emptyList();
}
private static QuickFixFactory factory() {
@@ -228,4 +245,8 @@ public class ModuleHighlightUtil {
private static TextRange range(PsiJavaModule module) {
return new TextRange(module.getTextOffset(), module.getNameElement().getTextRange().getEndOffset());
}
private static PsiElement range(PsiJavaCodeReferenceElement refElement) {
return ObjectUtils.notNull(refElement.getReferenceNameElement(), refElement);
}
}
@@ -92,7 +92,8 @@ class ReportMissingOrExcessiveInlineHint : AnAction() {
}
private fun showHint(editor: Editor) {
ApplicationManager.getApplication().invokeLater {
//hack, in most cases hint will not be shown without invokeLater, see IDEA-CR-13295
ApplicationManager.getApplication().invokeLater {
HintManager.getInstance().showInformationHint(editor, "Troubled inline hint was reported")
}
}
@@ -15,10 +15,14 @@
*/
package com.intellij.psi;
import org.jetbrains.annotations.Nullable;
/**
* Represents a {@code uses} statement of a Java module declaration.
*
* @since 2016.3
*/
public interface PsiUsesStatement extends PsiElement {
@Nullable
PsiJavaCodeReferenceElement getClassReference();
}
@@ -175,6 +175,9 @@ public class PsiJavaCodeReferenceElementImpl extends CompositePsiElement impleme
PsiJavaCodeReferenceCodeFragment fragment = (PsiJavaCodeReferenceCodeFragment)treeParent.getPsi();
return fragment.isClassesAccepted() ? CLASS_FQ_OR_PACKAGE_NAME_KIND : PACKAGE_NAME_KIND;
}
if (i == JavaElementType.USES_STATEMENT) {
return CLASS_FQ_NAME_KIND;
}
diagnoseUnknownParent();
return CLASS_NAME_KIND;
@@ -17,16 +17,25 @@ package com.intellij.psi.impl.source;
import com.intellij.psi.JavaElementVisitor;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiJavaCodeReferenceElement;
import com.intellij.psi.PsiUsesStatement;
import com.intellij.psi.impl.source.tree.CompositePsiElement;
import com.intellij.psi.impl.source.tree.JavaElementType;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class PsiUsesStatementImpl extends CompositePsiElement implements PsiUsesStatement {
public PsiUsesStatementImpl() {
super(JavaElementType.USES_STATEMENT);
}
@Nullable
@Override
public PsiJavaCodeReferenceElement getClassReference() {
return PsiTreeUtil.getChildOfType(this, PsiJavaCodeReferenceElement.class);
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof JavaElementVisitor) {
@@ -402,6 +402,8 @@ package.not.found=Package not found: {0}
package.is.empty=Package is empty: {0}
module.duplicate.export=Duplicate export: {0}
module.self.export=Exports to itself
module.service.enum=The service definition is an enum: {0}
module.duplicate.uses=Duplicate uses: {0}
feature.generics=Generics
feature.annotations=Annotations
@@ -81,6 +81,27 @@ class ModuleHighlightingTest : LightCodeInsightFixtureTestCase() {
}""".trimIndent())
}
fun testUses() {
addFile("pkg/main/C.java", "package pkg.main;\nclass C { }")
addFile("pkg/main/E.java", "package pkg.main;\npublic enum E { }")
doTest("""
module M {
uses pkg.<error descr="Cannot resolve symbol 'main'">main</error>;
uses pkg.main.<error descr="Cannot resolve symbol 'X'">X</error>;
uses pkg.main.<error descr="'pkg.main.C' is not public in 'pkg.main'. Cannot be accessed from outside package">C</error>;
uses pkg.main.<error descr="The service definition is an enum: E">E</error>;
}""".trimIndent())
}
fun testDuplicateUses() {
addFile("pkg/main/C.java", "package pkg.main;\npublic class C { }")
doTest("""
module M {
uses pkg.main.C;
<error descr="Duplicate uses: pkg.main.C">uses pkg. main . /*...*/ C;</error>
}""".trimIndent())
}
//<editor-fold desc="Helpers.">
private fun addFile(path: String, text: String) = VfsTestUtil.createFile(LightPlatformTestCase.getSourceRoot(), path, text)
@@ -786,4 +786,7 @@ rainbow.highlighter.colors.description=List of colors for rainbow highlighter in
ide.new.icons=false
ide.new.icons.restartRequired=true
ide.new.icons.description=Trying new platform icons
ide.new.icons.description=Trying new platform icons
ide.remote.interpreters.use.rsync=true
ide.remote.interpreters.use.rsync.description=Use rsync utility to synchronize remote interpreters and local stubs