mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-08 15:09:39 +07:00
IDEA-64131 support for links in comments
This commit is contained in:
@@ -15,8 +15,11 @@
|
||||
*/
|
||||
package com.intellij.psi.impl.source.javadoc;
|
||||
|
||||
import com.intellij.psi.JavaDocTokenType;
|
||||
import com.intellij.psi.JavaElementVisitor;
|
||||
import com.intellij.psi.PsiElementVisitor;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry;
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement;
|
||||
import com.intellij.psi.javadoc.PsiDocToken;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
@@ -42,6 +45,15 @@ public class PsiDocTokenImpl extends LeafPsiElement implements PsiDocToken{
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiReference[] getReferences() {
|
||||
if (getTokenType() == JavaDocTokenType.DOC_COMMENT_DATA) {
|
||||
return ReferenceProvidersRegistry.getReferencesFromProviders(this, PsiDocToken.class);
|
||||
}
|
||||
return super.getReferences();
|
||||
}
|
||||
|
||||
public String toString(){
|
||||
return "PsiDocToken:" + getTokenType().toString();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* <a href="http://www.unicode.org/unicode/standard/standard.html">
|
||||
* <i>The Unicode Standard</i></a>
|
||||
*/
|
||||
class LinksInJavaDoc {
|
||||
// Since Java 7 classloading is parallel on parallel capable classloader (http://docs.oracle.com/javase/7/docs/technotes/guides/lang/cl-mt.html)
|
||||
// Parallel classloading avoids deadlocks like https://youtrack.jetbrains.com/issue/IDEA-131621,
|
||||
}
|
||||
@@ -4,10 +4,17 @@ import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInspection.LocalInspectionTool;
|
||||
import com.intellij.codeInspection.javaDoc.JavaDocLocalInspection;
|
||||
import com.intellij.codeInspection.javaDoc.JavaDocReferenceInspection;
|
||||
import com.intellij.openapi.paths.WebReference;
|
||||
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiRecursiveElementWalkingVisitor;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
public class JavadocHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
private static final String BASE_PATH = "/codeInsight/daemonCodeAnalyzer/javaDoc";
|
||||
@@ -107,6 +114,33 @@ public class JavadocHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testLinksInJavaDoc() throws Exception {
|
||||
configureByFile(BASE_PATH + "/" + getTestName(false) + ".java");
|
||||
final List<WebReference> refs = new ArrayList<WebReference>();
|
||||
myFile.accept(new PsiRecursiveElementWalkingVisitor() {
|
||||
@Override
|
||||
public void visitElement(PsiElement element) {
|
||||
for(PsiReference ref:element.getReferences()) {
|
||||
if (ref instanceof WebReference) refs.add((WebReference)ref);
|
||||
}
|
||||
|
||||
super.visitElement(element);
|
||||
}
|
||||
});
|
||||
|
||||
String[] targets = {"http://www.unicode.org/unicode/standard/standard.html",
|
||||
"http://docs.oracle.com/javase/7/docs/technotes/guides/lang/cl-mt.html",
|
||||
"https://youtrack.jetbrains.com/issue/IDEA-131621"};
|
||||
assertTrue(refs.size() == targets.length);
|
||||
int i = 0;
|
||||
|
||||
for(WebReference ref:refs) {
|
||||
assertEquals(ref.getCanonicalText(), targets[i++]);
|
||||
assertTrue(ref.isSoft());
|
||||
assertNotNull(ref.resolve());
|
||||
}
|
||||
}
|
||||
|
||||
protected void doTest() throws Exception {
|
||||
super.doTest(BASE_PATH + "/" + getTestName(false) + ".java", true, false);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.codeInsight.documentation;
|
||||
|
||||
import com.intellij.openapi.paths.GlobalPathReferenceProvider;
|
||||
import com.intellij.openapi.paths.PathReferenceManager;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.UserDataCache;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.PsiReferenceProvider;
|
||||
import com.intellij.psi.util.CachedValue;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Created by Maxim.Mossienko on 12/19/2014.
|
||||
*/
|
||||
public class ArbitraryPlaceUrlReferenceProvider extends PsiReferenceProvider {
|
||||
public static final ArbitraryPlaceUrlReferenceProvider INSTANCE = new ArbitraryPlaceUrlReferenceProvider();
|
||||
|
||||
private static final Pattern urlPattern = Pattern.compile("((mailto\\:|(news|(ht|f)tp(s?))\\://){1}[^\\s\\),\"']+)");
|
||||
private static final UserDataCache<CachedValue<PsiReference[]>, PsiElement, Object> ourRefsCache = new UserDataCache<CachedValue<PsiReference[]>, PsiElement, Object>("psielement.url.refs") {
|
||||
private final AtomicReference<GlobalPathReferenceProvider> myReferenceProvider = new AtomicReference<GlobalPathReferenceProvider>();
|
||||
|
||||
@Override
|
||||
protected CachedValue<PsiReference[]> compute(final PsiElement element, Object p) {
|
||||
return CachedValuesManager
|
||||
.getManager(element.getProject()).createCachedValue(new CachedValueProvider<PsiReference[]>() {
|
||||
public Result<PsiReference[]> compute() {
|
||||
Matcher matcher = urlPattern.matcher(element.getText());
|
||||
|
||||
List<PsiReference> refs = null;
|
||||
GlobalPathReferenceProvider provider = myReferenceProvider.get();
|
||||
|
||||
while (matcher.find()) {
|
||||
final int start = matcher.start();
|
||||
final int end = matcher.end();
|
||||
if (refs == null) refs = new SmartList<PsiReference>();
|
||||
if (provider == null) {
|
||||
provider = (GlobalPathReferenceProvider)PathReferenceManager.getInstance().getGlobalWebPathReferenceProvider();
|
||||
myReferenceProvider.lazySet(provider);
|
||||
}
|
||||
|
||||
provider.createUrlReference(element, matcher.group(0), new TextRange(start, end), refs);
|
||||
}
|
||||
|
||||
return new Result<PsiReference[]>(refs != null ? refs.toArray(new PsiReference[refs.size()]) : PsiReference.EMPTY_ARRAY,
|
||||
element);
|
||||
}
|
||||
}, false);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiReference[] getReferencesByElement(@NotNull final PsiElement element, @NotNull ProcessingContext context) {
|
||||
return ourRefsCache.get(element, null).getValue();
|
||||
}
|
||||
}
|
||||
@@ -49,14 +49,23 @@ public class GlobalPathReferenceProvider implements PathReferenceProvider {
|
||||
if (manipulator == null) {
|
||||
return false;
|
||||
}
|
||||
final TextRange range = manipulator.getRangeInElement(psiElement);
|
||||
final String s = range.substring(psiElement.getText());
|
||||
if (isWebReferenceUrl(s)) {
|
||||
references.add(new WebReference(psiElement, range));
|
||||
return createUrlReference(
|
||||
psiElement,
|
||||
manipulator.getRangeInElement(psiElement).substring(psiElement.getText()),
|
||||
manipulator.getRangeInElement(psiElement),
|
||||
references
|
||||
);
|
||||
}
|
||||
|
||||
public boolean createUrlReference(@NotNull PsiElement psiElement,
|
||||
String url,
|
||||
TextRange rangeInElement, @NotNull List<PsiReference> references) {
|
||||
if (isWebReferenceUrl(url)) {
|
||||
references.add(new WebReference(psiElement, rangeInElement));
|
||||
return true;
|
||||
}
|
||||
else if (s.contains("://") || s.startsWith("//") || startsWithAllowedPrefix(s)) {
|
||||
final PsiReference reference = PsiReferenceBase.createSelfReference(psiElement, psiElement);
|
||||
references.add(reference);
|
||||
else if (url.contains("://") || url.startsWith("//") || startsWithAllowedPrefix(url)) {
|
||||
references.add(PsiReferenceBase.createSelfReference(psiElement, psiElement));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -16,11 +16,13 @@
|
||||
package com.intellij.psi.impl.source.resolve.reference.impl.providers;
|
||||
|
||||
import com.intellij.codeInsight.AnnotationUtil;
|
||||
import com.intellij.codeInsight.documentation.ArbitraryPlaceUrlReferenceProvider;
|
||||
import com.intellij.codeInspection.i18n.JavaI18nUtil;
|
||||
import com.intellij.patterns.PlatformPatterns;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.filters.ElementFilter;
|
||||
import com.intellij.psi.filters.position.FilterPattern;
|
||||
import com.intellij.psi.javadoc.PsiDocToken;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -52,5 +54,8 @@ public class JavaReferenceContributor extends PsiReferenceContributor{
|
||||
return true;
|
||||
}
|
||||
})), filePathReferenceProvider);
|
||||
registrar.registerReferenceProvider(PlatformPatterns.psiElement(PsiDocToken.class), ArbitraryPlaceUrlReferenceProvider.INSTANCE);
|
||||
// todo register for all ?
|
||||
registrar.registerReferenceProvider(PlatformPatterns.psiElement(PsiComment.class), ArbitraryPlaceUrlReferenceProvider.INSTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user