Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.redhat.ceylon.ceylondoc.LinkRenderer Maven / Gradle / Ivy
package com.redhat.ceylon.ceylondoc;
import static com.redhat.ceylon.ceylondoc.CeylondMessages.msg;
import static com.redhat.ceylon.ceylondoc.Util.getAnnotation;
import static com.redhat.ceylon.ceylondoc.Util.isAbbreviatedType;
import static com.redhat.ceylon.ceylondoc.Util.normalizeSpaces;
import static com.redhat.ceylon.model.typechecker.util.TypePrinter.abbreviateCallable;
import static com.redhat.ceylon.model.typechecker.util.TypePrinter.abbreviateEntry;
import static com.redhat.ceylon.model.typechecker.util.TypePrinter.abbreviateIterable;
import static com.redhat.ceylon.model.typechecker.util.TypePrinter.abbreviateOptional;
import static com.redhat.ceylon.model.typechecker.util.TypePrinter.abbreviateSequence;
import static com.redhat.ceylon.model.typechecker.util.TypePrinter.abbreviateSequential;
import static com.redhat.ceylon.model.typechecker.util.TypePrinter.abbreviateTuple;
import java.io.File;
import java.io.IOException;
import java.io.Writer;
import java.net.HttpURLConnection;
import java.net.Proxy;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import com.redhat.ceylon.common.Constants;
import com.redhat.ceylon.common.config.DefaultToolOptions;
import com.redhat.ceylon.compiler.java.codegen.Decl;
import com.redhat.ceylon.compiler.typechecker.tree.Node;
import com.redhat.ceylon.compiler.typechecker.tree.Tree;
import com.redhat.ceylon.compiler.typechecker.tree.Visitor;
import com.redhat.ceylon.model.loader.AbstractModelLoader;
import com.redhat.ceylon.model.typechecker.model.Annotated;
import com.redhat.ceylon.model.typechecker.model.Annotation;
import com.redhat.ceylon.model.typechecker.model.Class;
import com.redhat.ceylon.model.typechecker.model.ClassOrInterface;
import com.redhat.ceylon.model.typechecker.model.Declaration;
import com.redhat.ceylon.model.typechecker.model.Element;
import com.redhat.ceylon.model.typechecker.model.Function;
import com.redhat.ceylon.model.typechecker.model.FunctionOrValue;
import com.redhat.ceylon.model.typechecker.model.Interface;
import com.redhat.ceylon.model.typechecker.model.Module;
import com.redhat.ceylon.model.typechecker.model.NothingType;
import com.redhat.ceylon.model.typechecker.model.Package;
import com.redhat.ceylon.model.typechecker.model.Type;
import com.redhat.ceylon.model.typechecker.model.Referenceable;
import com.redhat.ceylon.model.typechecker.model.Scope;
import com.redhat.ceylon.model.typechecker.model.TypeAlias;
import com.redhat.ceylon.model.typechecker.model.TypeDeclaration;
import com.redhat.ceylon.model.typechecker.model.TypeParameter;
import com.redhat.ceylon.model.typechecker.model.TypedDeclaration;
import com.redhat.ceylon.model.typechecker.model.Unit;
import com.redhat.ceylon.model.typechecker.model.Value;
import com.redhat.ceylon.model.typechecker.util.TypePrinter;
public class LinkRenderer {
private Object to;
private Object from;
private CeylonDocTool ceylonDocTool;
private Writer writer;
private String customText;
private boolean withinText;
private Referenceable scope;
private String anchor;
private boolean printAbbreviated = true ;
private boolean printTypeParameters = true ;
private boolean printTypeParameterDetail = false ;
private boolean printWikiStyleLinks = false ;
private boolean printLinkDropdownMenu = true ;
private boolean printParenthesisAfterMethodName = true ;
private boolean printMemberContainerName = true ;
private final TypePrinter producedTypeNamePrinter = new TypePrinter() {
@Override
public String getSimpleDeclarationName (Declaration declaration, Unit unit) {
String result = null ;
if (declaration instanceof ClassOrInterface || declaration instanceof NothingType) {
TypeDeclaration type = (TypeDeclaration) declaration;
if (isLinkable(type)) {
String typeUrl = getUrl(type, null );
if (typeUrl != null ) {
result = buildLinkElement(typeUrl, getLinkText(type), "Go to " + type.getQualifiedNameString());
}
}
if ( result == null ) {
result = buildSpanElementWithNameAndTooltip(declaration);
}
} else if (declaration instanceof TypeParameter) {
result = " " + declaration.getName(unit) + " " ;
} else if (declaration instanceof TypedDeclaration) {
result = processTypedDeclaration((TypedDeclaration) declaration);
} else if (declaration instanceof TypeAlias) {
result = processTypeAlias((TypeAlias) declaration);
} else {
result = buildSpanElementWithNameAndTooltip(declaration);
}
return encodeResult(result);
}
@Override
public boolean printAbbreviated () {
return printAbbreviated;
}
@Override
public boolean printTypeParameters () {
return printTypeParameters;
}
@Override
public boolean printTypeParameterDetail () {
return printTypeParameterDetail;
}
@Override
public boolean printQualifyingType () {
return false ;
}
};
public LinkRenderer (CeylonDocTool ceylonDocTool, Writer writer, Object from) {
this .ceylonDocTool = ceylonDocTool;
this .writer = writer;
this .from = from;
}
public LinkRenderer (LinkRenderer linkRenderer) {
this .to = linkRenderer.to;
this .from = linkRenderer.from;
this .ceylonDocTool = linkRenderer.ceylonDocTool;
this .writer = linkRenderer.writer;
this .customText = linkRenderer.customText;
this .scope = linkRenderer.scope;
this .anchor = linkRenderer.anchor;
this .printAbbreviated = linkRenderer.printAbbreviated;
this .printTypeParameters = linkRenderer.printTypeParameters;
this .printTypeParameterDetail = linkRenderer.printTypeParameterDetail;
this .printLinkDropdownMenu = linkRenderer.printLinkDropdownMenu;
}
public LinkRenderer to (Object to) {
this .to = to;
return this ;
}
public LinkRenderer useCustomText (String customText) {
this .customText = customText;
return this ;
}
public LinkRenderer withinText (boolean text) {
withinText = text;
return this ;
}
public LinkRenderer useScope (Referenceable scope) {
this .scope = scope;
return this ;
}
public LinkRenderer useAnchor (String anchor) {
this .anchor = anchor;
return this ;
}
public LinkRenderer printAbbreviated (boolean printAbbreviated) {
this .printAbbreviated = printAbbreviated;
return this ;
}
public LinkRenderer printTypeParameters (boolean printTypeParameters) {
this .printTypeParameters = printTypeParameters;
return this ;
}
public LinkRenderer printTypeParameterDetail (boolean printTypeParameterDetail) {
this .printTypeParameterDetail = printTypeParameterDetail;
return this ;
}
public LinkRenderer printWikiStyleLinks (boolean printWikiStyleLinks) {
this .printWikiStyleLinks = printWikiStyleLinks;
return this ;
}
public LinkRenderer printLinkDropdownMenu (boolean printLinkDropdownMenu) {
this .printLinkDropdownMenu = printLinkDropdownMenu;
return this ;
}
public LinkRenderer printParenthesisAfterMethodName (boolean printParenthesisAfterMethodName) {
this .printParenthesisAfterMethodName = printParenthesisAfterMethodName;
return this ;
}
public LinkRenderer printMemberContainerName (boolean printMemberContainerName) {
this .printMemberContainerName = printMemberContainerName;
return this ;
}
public String getLink () {
String link = null ;
if (to instanceof String) {
if (printWikiStyleLinks) {
link = processWikiLink((String) to);
} else {
link = processAnnotationParam((String) to);
}
} else if (to instanceof Type) {
link = processProducedType((Type) to);
} else if (to instanceof Declaration) {
link = processDeclaration(((Declaration) to));
} else if (to instanceof Module) {
link = processModule((Module) to);
} else if (to instanceof Package) {
link = processPackage((Package) to);
}
return link;
}
public String getUrl () {
return getUrl(to, anchor);
}
public String getResourceUrl (String to) throws IOException {
return ceylonDocTool.getResourceUrl(from, to);
}
public String getSrcUrl (Object to) throws IOException {
return ceylonDocTool.getSrcUrl(from, to);
}
public void write () throws IOException {
writer.write(getLink());
}
private String processModule (Module module ) {
String moduleUrl = getUrl(module , anchor);
if (moduleUrl != null ) {
return buildLinkElement(moduleUrl, module .getNameAsString(), "Go to module" );
} else {
return module .getNameAsString();
}
}
private String processPackage (Package pkg) {
String pkgUrl = getUrl(pkg, anchor);
if (pkgUrl != null ) {
return buildLinkElement(pkgUrl, customText != null ? customText : pkg.getNameAsString(), "Go to package " + pkg.getNameAsString());
} else {
return pkg.getNameAsString();
}
}
private String processDeclaration (Declaration decl) {
if (decl instanceof TypeDeclaration) {
return processProducedType(((TypeDeclaration) decl).getType());
} else {
return processTypedDeclaration((TypedDeclaration) decl);
}
}
private String processProducedType (Type producedType) {
String result;
boolean wasWithinText = withinText;
withinText = false ;
try {
result = producedTypeNamePrinter.print(producedType, null );
}
finally {
withinText = wasWithinText;
}
result = decodeResult(result);
if (withinText && customText==null ) {
result = " " + result + "
" ;
}
result = decorateWithLinkDropdownMenu(result, producedType);
return result;
}
private String processTypedDeclaration (TypedDeclaration decl) {
String declName = Util.getDeclarationName(decl);
Scope declContainer = decl.getContainer();
if ( isLinkable(decl) ) {
String url = getUrl(declContainer, declName);
if ( url != null ) {
return buildLinkElement(url, getLinkText(decl), "Go to " + decl.getQualifiedNameString());
}
}
String result = declName;
if (withinText) {
result = " " + result + "
" ;
}
if (customText != null ) {
result = customText;
}
return result;
}
private String processTypeAlias (TypeAlias alias) {
String aliasName = alias.getName();
Scope aliasContainer = alias.getContainer();
if (isLinkable(alias)) {
String url = getUrl(aliasContainer, aliasName);
if (url != null ) {
return buildLinkElement(url, aliasName, "Go to " + alias.getQualifiedNameString());
}
}
return buildSpanElementWithNameAndTooltip(alias);
}
private String processWikiLink (final String docLinkText) {
Tree.DocLink docLink = findDocLink(docLinkText, scope);
if (docLink == null && scope instanceof Declaration) {
Declaration refinedDeclaration = ((Declaration) scope).getRefinedDeclaration();
if (refinedDeclaration != scope) {
docLink = findDocLink(docLinkText, refinedDeclaration);
}
}
if (docLink != null ) {
if (docLink.getQualified() != null && docLink.getQualified().size() > 0 ) {
return processDeclaration(docLink.getQualified().get(docLink.getQualified().size() - 1 ));
} else if (docLink.getBase() != null ) {
printAbbreviated = !isAbbreviatedType(docLink.getBase());
return processDeclaration(docLink.getBase());
} else if (docLink.getModule() != null ) {
return processModule(docLink.getModule());
} else if (docLink.getPkg() != null ) {
return processPackage(docLink.getPkg());
}
}
if (docLink != null && scope instanceof Annotated) {
Annotation docAnnotation = getAnnotation(scope.getUnit(), ((Annotated) scope).getAnnotations(), "doc" );
if (docAnnotation != null ) {
ceylonDocTool.warningBrokenLink(docLinkText, docLink, scope);
}
}
return getUnresolvableLink(docLinkText);
}
private String processAnnotationParam (String text) {
if ( text.equals("module" )) {
Module mod = getCurrentModule();
if ( mod != null ) {
return processModule(mod);
}
}
if (text.startsWith("module " )) {
String modName = text.substring(7 );
for (Module m : ceylonDocTool.getTypeChecker().getContext().getModules().getListOfModules()) {
if (m.getNameAsString().equals(modName)) {
return processModule(m);
}
}
}
if ( text.equals("package" )) {
Package pkg = getCurrentPackage();
if (pkg != null ) {
return processPackage(pkg);
}
}
if (text.startsWith("package " )) {
String pkgName = text.substring(8 );
for (Module m : ceylonDocTool.getTypeChecker().getContext().getModules().getListOfModules()) {
if (pkgName.startsWith(m.getNameAsString() + "." )) {
Package pkg = m.getPackage(pkgName);
if (pkg != null ) {
return processPackage(pkg);
}
}
}
}
if ( text.equals("interface" ) ) {
Interface interf = getCurrentInterface();
if ( interf != null ) {
return processProducedType(interf.getType());
}
}
if ( text.equals("class" ) ) {
Class clazz = getCurrentClass();
if ( clazz != null ) {
return processProducedType(clazz.getType());
}
}
String declName;
Scope currentScope;
int pkgSeparatorIndex = text.indexOf("::" );
if ( pkgSeparatorIndex == -1 ) {
declName = text;
currentScope = resolveScope(scope);
} else {
String pkgName = text.substring(0 , pkgSeparatorIndex);
declName = text.substring(pkgSeparatorIndex+2 , text.length());
currentScope = ceylonDocTool.getCurrentModule().getPackage(pkgName);
}
String[] declNames = declName.split("\\." );
Declaration currentDecl = null ;
boolean isNested = false ;
for (String currentDeclName : declNames) {
currentDecl = resolveDeclaration(currentScope, currentDeclName, isNested);
if (currentDecl != null ) {
if ( isValueWithTypeObject(currentDecl) ) {
TypeDeclaration objectType = ((Value)currentDecl).getTypeDeclaration();
currentScope = objectType;
currentDecl = objectType;
} else {
currentScope = resolveScope(currentDecl);
}
isNested = true ;
} else {
break ;
}
}
if (currentDecl != null && !isParameter(currentDecl)) {
if (currentDecl instanceof TypeDeclaration) {
return processProducedType(((TypeDeclaration) currentDecl).getType());
} else {
return processTypedDeclaration((TypedDeclaration) currentDecl);
}
} else {
return getUnresolvableLink(text);
}
}
private boolean isLinkable (Declaration decl) {
if ( decl == null ) {
return false ;
}
if ( decl.isParameter() ) {
return true ;
}
if ( !ceylonDocTool.isIncludeNonShared() ) {
if ( !decl.isShared() ) {
return false ;
}
Scope c = decl.getContainer();
while (c != null ) {
boolean isShared = true ;
if ( c instanceof Declaration ) {
isShared = ((Declaration) c).isShared();
}
if ( c instanceof Package ) {
isShared = ((Package) c).isShared();
}
if ( !isShared ) {
return false ;
}
c = c.getContainer();
}
}
return true ;
}
private boolean isValueWithTypeObject (Declaration decl) {
if (Decl.isValue(decl)) {
TypeDeclaration typeDeclaration = ((Value) decl).getTypeDeclaration();
if (typeDeclaration instanceof Class && typeDeclaration.isAnonymous()) {
return true ;
}
}
return false ;
}
private boolean isParameter (Declaration decl) {
return decl instanceof FunctionOrValue
&& ((FunctionOrValue)decl).isParameter();
}
private Declaration resolveDeclaration (Scope scope, String declName, boolean isNested) {
Declaration decl = null ;
if (scope != null ) {
decl = scope.getMember(declName, null , false );
if (decl == null && !isNested && scope instanceof Element) {
decl = ((Element) scope).getUnit().getImportedDeclaration(declName, null , false );
}
if (decl == null && !isNested && !scope.getQualifiedNameString().equals(AbstractModelLoader.CEYLON_LANGUAGE) ) {
decl = resolveDeclaration(scope.getContainer(), declName, isNested);
}
if (decl == null && declName.equals("Nothing" ) && scope.getQualifiedNameString().equals(AbstractModelLoader.CEYLON_LANGUAGE)) {
decl = new NothingType(((Package) scope).getUnit());
}
} else {
Package pkg = ceylonDocTool.getCurrentModule().getPackage(AbstractModelLoader.CEYLON_LANGUAGE);
if (pkg != null ) {
decl = resolveDeclaration(pkg, declName, isNested);
}
}
return decl;
}
private Scope resolveScope (Referenceable referenceable) {
if (referenceable instanceof Module) {
return ((Module) referenceable).getPackage(referenceable.getNameAsString());
} else if (referenceable instanceof Scope) {
return (Scope) referenceable;
} else if (referenceable instanceof Declaration) {
return ((Declaration) referenceable).getContainer();
} else {
return null ;
}
}
private boolean isInCurrentModule (Object obj) {
Module objModule = null ;
if (obj instanceof Module) {
objModule = (Module) obj;
} else if (obj instanceof Scope) {
objModule = getPackage((Scope) obj).getModule();
} else if (obj instanceof Element) {
objModule = getPackage(((Element) obj).getScope()).getModule();
}
Module currentModule = ceylonDocTool.getCurrentModule();
if (currentModule != null && objModule != null ) {
return currentModule.equals(objModule);
}
return false ;
}
private String getUnresolvableLink (final String docLinkText) {
StringBuilder unresolvable = new StringBuilder();
unresolvable.append(" " );
boolean hasCustomText =
customText != null && !customText.equals(docLinkText);
if (hasCustomText) {
unresolvable.append(customText);
unresolvable.append(" (" );
}
if (withinText) unresolvable.append(" " );
int index = docLinkText.indexOf('|' )+1 ;
unresolvable.append(docLinkText.substring(index));
if (withinText) unresolvable.append("
" );
if (hasCustomText) {
unresolvable.append(")" );
}
unresolvable.append(" " );
return unresolvable.toString();
}
private String getLinkText (Declaration decl) {
if (customText != null ) {
return customText;
}
else {
String name = Util.getDeclarationName(decl);
if ( scope != null && scope.getUnit() != null ) {
name = scope.getUnit().getAliasedName(decl, name);
}
String result;
if (decl instanceof TypeDeclaration) {
result = " " + name + " " ;
}
else {
if (decl instanceof Function && printParenthesisAfterMethodName) {
name = name + "()" ;
}
result = " " + name + " " ;
}
if (printMemberContainerName && decl.isMember() && decl.getContainer() != from) {
result = getLinkText((Declaration) decl.getContainer()) + '.' + result;
}
return result;
}
}
private Package getPackage (Scope scope) {
while (!(scope instanceof Package)) {
scope = scope.getContainer();
}
return (Package) scope;
}
private String getUrl (Object to, String anchor) {
String url;
List methods = new ArrayList();
while (to instanceof Function){
Function method = (Function) to;
methods.add(method);
to = method.getContainer();
}
if (isInCurrentModule(to)) {
url = getLocalUrl(to);
} else {
url = getExternalUrl(to);
}
if (url != null && anchor != null ) {
String sectionPackageAnchor = "#section-package" ;
if (url.endsWith(sectionPackageAnchor)) {
url = url.substring(0 , url.length() - sectionPackageAnchor.length());
}
StringBuilder fragment = new StringBuilder();
if (!methods.isEmpty()) {
Collections.reverse(methods);
for (Function method : methods) {
fragment.append(method.getName());
fragment.append("-" );
}
}
fragment.append(anchor);
url = url + "#" + fragment;
}
return url;
}
private String getLocalUrl (Object to) {
try {
return ceylonDocTool.getObjectUrl(from, to);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private String getExternalUrl (Object to) {
String url = null ;
if (to instanceof Module) {
url = getExternalModuleUrl((Module)to);
if (url != null ) {
url += "index.html" ;
}
} else if (to instanceof Package) {
Package pkg = (Package)to;
url = getExternalModuleUrl(pkg.getModule());
if (url != null ) {
url += buildPackageUrlPath(pkg);
url += "index.html" ;
}
} else if (to instanceof ClassOrInterface) {
ClassOrInterface klass = (ClassOrInterface) to;
Package pkg = getPackage(klass);
url = getExternalModuleUrl(pkg.getModule());
if (url != null ) {
url += buildPackageUrlPath(pkg);
url += ceylonDocTool.getFileName(klass);
}
}
return url;
}
private String getExternalModuleUrl (Module module ) {
if ( ceylonDocTool.getLinks() != null ) {
String moduleName = module .getNameAsString();
for (String link : ceylonDocTool.getLinks()) {
String[] linkParts = divideToPatternAndUrl(link);
String moduleNamePattern = linkParts[0 ];
String moduleRepoUrl = linkParts[1 ];
if (moduleNamePattern == null ) {
String moduleDocUrl = buildModuleUrl(moduleRepoUrl, module );
if (isHttpProtocol(moduleDocUrl) && checkHttpUrlExist(moduleDocUrl)) {
return moduleDocUrl;
}
if (isFileProtocol(moduleDocUrl) && checkFileUrlExist(moduleDocUrl)) {
return moduleDocUrl;
}
} else if (moduleName.startsWith(moduleNamePattern)) {
return buildModuleUrl(moduleRepoUrl, module );
}
}
}
return null ;
}
private String buildLinkElement (String url, String text, String toolTip) {
StringBuilder linkBuilder = new StringBuilder();
linkBuilder.append(" " );
if (customText==null && withinText) {
linkBuilder.append(" " );
}
linkBuilder.append(text);
if (customText==null && withinText) {
linkBuilder.append("
" );
}
linkBuilder.append(" " );
return linkBuilder.toString();
}
private String buildSpanElementWithNameAndTooltip (Declaration d) {
StringBuilder spanBuilder = new StringBuilder();
spanBuilder.append(" " );
if (withinText) spanBuilder.append(" " );
spanBuilder.append(getLinkText(d));
if (withinText) spanBuilder.append("
" );
spanBuilder.append(" " );
return spanBuilder.toString();
}
private String buildModuleUrl (String moduleRepoUrl, Module module ) {
StringBuilder moduleUrlBuilder = new StringBuilder();
moduleUrlBuilder.append(moduleRepoUrl);
if (!moduleRepoUrl.endsWith("/" )) {
moduleUrlBuilder.append("/" );
}
moduleUrlBuilder.append(Util.join("/" , module .getName()));
moduleUrlBuilder.append("/" );
moduleUrlBuilder.append(module .getVersion());
moduleUrlBuilder.append("/module-doc/api/" );
return moduleUrlBuilder.toString();
}
private String buildPackageUrlPath (Package pkg) {
List packagePath = pkg.getName().subList(pkg.getModule().getName().size(), pkg.getName().size());
if (!packagePath.isEmpty()) {
return Util.join("/" , packagePath) + "/" ;
}
return "" ;
}
public static String[] divideToPatternAndUrl(String link) {
String moduleRepoUrl = null ;
String moduleNamePattern = null ;
int indexOfSeparator = link.indexOf("=" );
if (indexOfSeparator != -1 ) {
moduleNamePattern = link.substring(0 , indexOfSeparator);
moduleRepoUrl = link.substring(indexOfSeparator + 1 );
} else {
moduleRepoUrl = link;
}
return new String[] { moduleNamePattern, moduleRepoUrl };
}
public static boolean isHttpProtocol (String url) {
return url.startsWith("http://" ) || url.startsWith("https://" );
}
public static boolean isFileProtocol (String url) {
return url.startsWith("file://" );
}
private boolean checkHttpUrlExist (String moduleUrl) {
Boolean result = ceylonDocTool.getModuleUrlAvailabilityCache().get(moduleUrl);
if ( result == null ) {
try {
URL url = new URL(moduleUrl + "index.html" );
HttpURLConnection con;
Proxy proxy = DefaultToolOptions.getDefaultProxy();
if (proxy != null ) {
con = (HttpURLConnection) url.openConnection(proxy);
} else {
con = (HttpURLConnection) url.openConnection();
}
con.setConnectTimeout((int ) DefaultToolOptions.getDefaultTimeout());
con.setReadTimeout((int ) DefaultToolOptions.getDefaultTimeout() * Constants.READ_TIMEOUT_MULTIPLIER);
con.setRequestMethod("HEAD" );
int responseCode = con.getResponseCode();
if ( responseCode == HttpURLConnection.HTTP_OK ) {
result = Boolean.TRUE;
} else {
ceylonDocTool.getLogger().warning(msg("info.urlDoesNotExist" , moduleUrl));
result = Boolean.FALSE;
}
}
catch (IOException e) {
ceylonDocTool.getLogger().warning(msg("info.urlDoesNotExist" , moduleUrl));
result = Boolean.FALSE;
}
ceylonDocTool.getModuleUrlAvailabilityCache().put(moduleUrl, result);
}
return result.booleanValue();
}
private boolean checkFileUrlExist (String moduleUrl) {
Boolean result = ceylonDocTool.getModuleUrlAvailabilityCache().get(moduleUrl);
if ( result == null ) {
File moduleDocDir = new File(moduleUrl.substring("file://" .length()));
if (moduleDocDir.isDirectory() && moduleDocDir.exists()) {
result = Boolean.TRUE;
} else {
ceylonDocTool.getLogger().warning(msg("info.urlDoesNotExist" , moduleUrl));
result = Boolean.FALSE;
}
ceylonDocTool.getModuleUrlAvailabilityCache().put(moduleUrl, result);
}
return result.booleanValue();
}
private static String encodeResult (String text) {
if (text != null ) {
text = text.replaceAll("<" , "#LT;" );
text = text.replaceAll(">" , "#GT;" );
}
return text;
}
private static String decodeResult (String text) {
if (text != null ) {
text = text.replaceAll("&" , "&" );
text = text.replaceAll("<" , "<" );
text = text.replaceAll(">" , ">" );
text = text.replaceAll("#LT;" , "<" );
text = text.replaceAll("#GT;" , ">" );
text = text.replaceAll("<in " , "< in " );
text = text.replaceAll(",in " , ", in " );
text = text.replaceAll("<out " , "< out " );
text = text.replaceAll(",out " , ", out " );
}
return text;
}
private String decorateWithLinkDropdownMenu (String link, Type producedType) {
if ( !printLinkDropdownMenu || !printAbbreviated || !canLinkToCeylonLanguageModule() ) {
return link;
}
List producedTypes = new ArrayList();
decompose(producedType, producedTypes);
boolean containsOptional = false ;
boolean containsSequential = false ;
boolean containsSequence = false ;
boolean containsIterable = false ;
boolean containsEntry = false ;
boolean containsCallable = false ;
boolean containsTuple = false ;
for (Type pt : producedTypes) {
if (abbreviateOptional(pt)) {
containsOptional = true ;
} else if (abbreviateSequential(pt) && !link.contains("'Go to ceylon.language::Sequential'" )) {
containsSequential = true ;
} else if (abbreviateSequence(pt) && !link.contains("'Go to ceylon.language::Sequence'" )) {
containsSequence = true ;
} else if (abbreviateIterable(pt) && !link.contains("'Go to ceylon.language::Iterable'" )) {
containsIterable = true ;
} else if (abbreviateEntry(pt) && !link.contains("'Go to ceylon.language::Entry'" )) {
containsEntry = true ;
} else if (abbreviateCallable(pt) && !link.contains("'Go to ceylon.language::Callable'" )) {
containsCallable = true ;
} else if (abbreviateTuple(pt) && !link.contains("'Go to ceylon.language::Tuple'" )) {
containsTuple = true ;
}
}
Unit unit = producedType.getDeclaration().getUnit();
if ( containsOptional || containsSequential || containsSequence || containsIterable || containsEntry || containsCallable || containsTuple ) {
StringBuilder sb = new StringBuilder();
sb.append(" " );
sb.append(link.replaceAll("class='link'" , "class='link type-identifier'" ));
sb.append(" " );
sb.append(" " );
sb.append(" " );
sb.append(" " );
sb.append(" " );
return sb.toString();
}
return link;
}
private boolean canLinkToCeylonLanguageModule () {
Module currentModule = ceylonDocTool.getCurrentModule();
if (currentModule.getNameAsString().equals(Module.LANGUAGE_MODULE_NAME)) {
return true ;
} else {
Module languageModule = currentModule.getLanguageModule();
String languageModuleUrl = getExternalModuleUrl(languageModule);
return languageModuleUrl != null ;
}
}
private void decompose (Type pt, List producedTypes) {
if (!producedTypes.contains(pt)) {
producedTypes.add(pt);
if (pt.isIntersection()) {
for (Type satisfiedType : pt.getSatisfiedTypes()) {
decompose(satisfiedType, producedTypes);
}
}
else if (pt.isUnion()) {
for (Type caseType : pt.getCaseTypes()) {
decompose(caseType, producedTypes);
}
}
if (!pt.getTypeArgumentList().isEmpty()) {
for (Type typeArgument : pt.getTypeArgumentList()) {
decompose(typeArgument, producedTypes);
}
}
}
}
private String getLinkMenuItem (Declaration decl, String description) {
String url = new LinkRenderer(this ).
to(decl).
useCustomText("" ).
printLinkDropdownMenu(false ).
printAbbreviated(false ).
printTypeParameters(false ).
getUrl();
StringBuilder sb = new StringBuilder();
sb.append(" " );
sb.append(" " );
sb.append("Go to " ).append(decl.getName()).append(" " );
sb.append(" " ).append(description).append(" " );
sb.append(" " );
sb.append(" " );
return sb.toString();
}
private Tree.DocLink findDocLink (final String docLinkText, Referenceable referenceable) {
final Tree.DocLink[] docLinks = new Tree.DocLink[1 ];
Node scopeNode = ceylonDocTool.getNode(referenceable);
if (scopeNode != null ) {
scopeNode.visit(new Visitor() {
@Override
public void visit (Tree.DocLink docLink) {
String s1 = normalizeSpaces(docLinkText);
String s2 = normalizeSpaces(docLink.getText());
if (s1.equals(s2)) {
docLinks[0 ] = docLink;
return ;
}
}
});
}
return docLinks[0 ];
}
private Module getCurrentModule () {
if (scope instanceof Module) {
return (Module) scope;
} else if (scope instanceof Package) {
return ((Package) scope).getModule();
} else if (scope instanceof Declaration) {
return scope.getUnit().getPackage().getModule();
}
return null ;
}
private Package getCurrentPackage () {
if (scope instanceof Module) {
return ((Module) scope).getRootPackage();
} else if (scope instanceof Package) {
return (Package) scope;
} else if (scope instanceof Declaration) {
return scope.getUnit().getPackage();
}
return null ;
}
private Interface getCurrentInterface () {
Object o = scope;
while (o != null ) {
if (o instanceof Interface) {
return (Interface) o;
} else if (o instanceof Declaration) {
o = ((Declaration) o).getContainer();
} else {
o = null ;
}
}
return null ;
}
private Class getCurrentClass () {
Object o = scope;
while (o != null ) {
if (o instanceof Class) {
return (Class) o;
} else if (o instanceof Declaration) {
o = ((Declaration) o).getContainer();
} else {
o = null ;
}
}
return null ;
}
}