blob: 60c19874fd86375b966f70bbf8d9ee114cfd199d [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2014 The Bazel Authors. All rights reserved.
David Chen24f2d992015-08-17 17:25:46 +00002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14package com.google.devtools.build.docgen.skylark;
15
fwe3d2c75c2017-07-20 15:19:18 +020016import com.google.common.collect.ImmutableList;
17import com.google.devtools.build.lib.collect.nestedset.NestedSet;
Damien Martin-Guillerez2ca9b722016-06-09 17:43:55 +000018import com.google.devtools.build.lib.skylarkinterface.Param;
cparsons0fcad772018-04-11 14:24:00 -070019import com.google.devtools.build.lib.skylarkinterface.SkylarkCallable;
John Field585d1a02015-12-16 16:03:52 +000020import com.google.devtools.build.lib.skylarkinterface.SkylarkModule;
21import com.google.devtools.build.lib.skylarkinterface.SkylarkSignature;
David Chen24f2d992015-08-17 17:25:46 +000022import com.google.devtools.build.lib.syntax.EvalUtils;
23import com.google.devtools.build.lib.syntax.FuncallExpression;
Francois-Rene Rideau0f7ba342015-08-31 16:16:21 +000024import com.google.devtools.build.lib.syntax.Runtime.NoneType;
David Chen24f2d992015-08-17 17:25:46 +000025import com.google.devtools.build.lib.syntax.SkylarkList;
Francois-Rene Rideau93ed7f12015-10-20 15:39:33 +000026import com.google.devtools.build.lib.syntax.SkylarkList.MutableList;
Francois-Rene Rideau4e994102015-09-17 22:41:28 +000027import com.google.devtools.build.lib.syntax.SkylarkList.Tuple;
cparsons0fcad772018-04-11 14:24:00 -070028import com.google.devtools.build.lib.syntax.StringModule;
29import java.lang.reflect.Method;
David Chen24f2d992015-08-17 17:25:46 +000030import java.util.Arrays;
David Chen24f2d992015-08-17 17:25:46 +000031import java.util.Map;
32
33/**
34 * Abstract class for containing documentation for a Skylark syntactic entity.
35 */
36abstract class SkylarkDoc {
37 protected static final String TOP_LEVEL_ID = "globals";
38
39 /**
40 * Returns a string containing the name of the entity being documented.
41 */
42 public abstract String getName();
43
44 /**
John Caterfd71be72016-07-29 14:59:22 +000045 * Returns a string containing the formatted HTML documentation of the entity being documented.
David Chen24f2d992015-08-17 17:25:46 +000046 */
John Cater5d8a44c2017-01-03 20:07:37 +000047 public abstract String getDocumentation();
David Chen24f2d992015-08-17 17:25:46 +000048
49 protected String getTypeAnchor(Class<?> returnType, Class<?> generic1) {
50 return getTypeAnchor(returnType) + " of " + getTypeAnchor(generic1) + "s";
51 }
52
53 protected String getTypeAnchor(Class<?> type) {
54 if (type.equals(Boolean.class) || type.equals(boolean.class)) {
Laurent Le Brun4f3b5822017-02-15 16:20:24 +000055 return "<a class=\"anchor\" href=\"bool.html\">bool</a>";
56 } else if (type.equals(int.class) || type.equals(Integer.class)) {
57 return "<a class=\"anchor\" href=\"int.html\">int</a>";
David Chen24f2d992015-08-17 17:25:46 +000058 } else if (type.equals(String.class)) {
59 return "<a class=\"anchor\" href=\"string.html\">string</a>";
60 } else if (Map.class.isAssignableFrom(type)) {
61 return "<a class=\"anchor\" href=\"dict.html\">dict</a>";
Francois-Rene Rideau93ed7f12015-10-20 15:39:33 +000062 } else if (type.equals(Tuple.class)) {
Francois-Rene Rideau4e994102015-09-17 22:41:28 +000063 return "<a class=\"anchor\" href=\"list.html\">tuple</a>";
fwe3d2c75c2017-07-20 15:19:18 +020064 } else if (type.equals(MutableList.class) || type.equals(ImmutableList.class)) {
David Chen24f2d992015-08-17 17:25:46 +000065 return "<a class=\"anchor\" href=\"list.html\">list</a>";
Francois-Rene Rideau93ed7f12015-10-20 15:39:33 +000066 } else if (type.equals(SkylarkList.class)) {
67 return "<a class=\"anchor\" href=\"list.html\">sequence</a>";
David Chen24f2d992015-08-17 17:25:46 +000068 } else if (type.equals(Void.TYPE) || type.equals(NoneType.class)) {
69 return "<a class=\"anchor\" href=\"" + TOP_LEVEL_ID + ".html#None\">None</a>";
fwe3d2c75c2017-07-20 15:19:18 +020070 } else if (type.equals(NestedSet.class)) {
71 return "<a class=\"anchor\" href=\"depset.html\">depset</a>";
David Chen24f2d992015-08-17 17:25:46 +000072 } else if (type.isAnnotationPresent(SkylarkModule.class)) {
Florian Weikerta469e8f2016-06-20 14:55:41 +000073 SkylarkModule module = type.getAnnotation(SkylarkModule.class);
74 if (module.documented()) {
75 return String.format("<a class=\"anchor\" href=\"%1$s.html\">%1$s</a>",
76 module.name());
77 }
David Chen24f2d992015-08-17 17:25:46 +000078 }
Florian Weikerta469e8f2016-06-20 14:55:41 +000079 return EvalUtils.getDataTypeNameFromClass(type);
David Chen24f2d992015-08-17 17:25:46 +000080 }
81
cparsons0fcad772018-04-11 14:24:00 -070082 // Omit self parameter from parameters in class methods.
83 protected static Param[] withoutSelfParam(SkylarkSignature annotation) {
Damien Martin-Guillerez014388c2016-06-14 10:28:31 +000084 Param[] params = annotation.parameters();
85 if (params.length > 0
86 && !params[0].named()
87 && (params[0].defaultValue() != null && params[0].defaultValue().isEmpty())
88 && params[0].positional()
David Chen24f2d992015-08-17 17:25:46 +000089 && annotation.objectType() != Object.class
90 && !FuncallExpression.isNamespace(annotation.objectType())) {
91 // Skip the self parameter, which is the first mandatory positional parameter.
Damien Martin-Guillerez014388c2016-06-14 10:28:31 +000092 return Arrays.copyOfRange(params, 1, params.length);
David Chen24f2d992015-08-17 17:25:46 +000093 } else {
Damien Martin-Guillerez014388c2016-06-14 10:28:31 +000094 return params;
David Chen24f2d992015-08-17 17:25:46 +000095 }
96 }
cparsons0fcad772018-04-11 14:24:00 -070097
98 // Omit self parameter from parameters in class methods.
99 protected static Param[] withoutSelfParam(SkylarkCallable annotation, Method method) {
100 Param[] params = annotation.parameters();
101 if (method.getDeclaringClass().equals(StringModule.class)) {
102 // Skip the self parameter, which is the first mandatory positional parameter.
103 return Arrays.copyOfRange(params, 1, params.length);
104 } else {
105 return params;
106 }
107 }
David Chen24f2d992015-08-17 17:25:46 +0000108}