PageRenderTime 39ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/python/python-psi-impl/src/com/jetbrains/python/psi/impl/ParamHelper.java

http://github.com/JetBrains/intellij-community
Java | 213 lines | 138 code | 33 blank | 42 comment | 19 complexity | c14411a13edee04fd3f1d0aaa79d73ab MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0, MPL-2.0-no-copyleft-exception, MIT, EPL-1.0, AGPL-1.0
  1. /*
  2. * Copyright 2000-2017 JetBrains s.r.o.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.jetbrains.python.psi.impl;
  17. import com.intellij.openapi.util.Pair;
  18. import com.intellij.util.containers.ContainerUtil;
  19. import com.jetbrains.python.psi.*;
  20. import com.jetbrains.python.psi.types.PyCallableParameter;
  21. import com.jetbrains.python.psi.types.PyCallableParameterImpl;
  22. import com.jetbrains.python.psi.types.TypeEvalContext;
  23. import org.jetbrains.annotations.NotNull;
  24. import org.jetbrains.annotations.Nullable;
  25. import java.util.ArrayList;
  26. import java.util.List;
  27. /**
  28. * Parameter-related things that should not belong directly to PyParameter.
  29. */
  30. public class ParamHelper {
  31. private ParamHelper() {
  32. }
  33. /**
  34. * Runs a {@link ParamWalker ParamWalker} down the array of parameters, recursively descending into tuple parameters.
  35. * If the array is from PyParamaterList.getParameters(), parameters are visited in the order of textual appearance
  36. * @param params where to walk
  37. * @param walker the walker with callbacks.
  38. */
  39. public static void walkDownParamArray(PyParameter[] params, ParamWalker walker) {
  40. walkDownParameters(ContainerUtil.map(params, PyCallableParameterImpl::psi), walker);
  41. }
  42. public static void walkDownParameters(@NotNull List<? extends PyCallableParameter> parameters, @NotNull ParamWalker walker) {
  43. int i = 0;
  44. for (PyCallableParameter parameter : parameters) {
  45. final PyParameter psi = parameter.getParameter();
  46. final boolean first = i == 0;
  47. final boolean last = i == parameters.size() - 1;
  48. if (psi instanceof PyTupleParameter) {
  49. final PyTupleParameter tupleParameter = (PyTupleParameter)psi;
  50. walker.enterTupleParameter(tupleParameter, first, last);
  51. walkDownParamArray(tupleParameter.getContents(), walker);
  52. walker.leaveTupleParameter(tupleParameter, first, last);
  53. }
  54. else if (psi instanceof PyNamedParameter) {
  55. walker.visitNamedParameter((PyNamedParameter)psi, first, last);
  56. }
  57. else if (psi instanceof PySlashParameter) {
  58. walker.visitSlashParameter((PySlashParameter)psi, first, last);
  59. }
  60. else if (psi instanceof PySingleStarParameter) {
  61. walker.visitSingleStarParameter((PySingleStarParameter)psi, first, last);
  62. }
  63. else {
  64. walker.visitNonPsiParameter(parameter, first, last);
  65. }
  66. i++;
  67. }
  68. }
  69. @NotNull
  70. public static String getPresentableText(PyParameter @NotNull [] parameters,
  71. boolean includeDefaultValue,
  72. @Nullable TypeEvalContext context) {
  73. return getPresentableText(ContainerUtil.map(parameters, PyCallableParameterImpl::psi), includeDefaultValue, context);
  74. }
  75. @NotNull
  76. public static String getPresentableText(@NotNull List<? extends PyCallableParameter> parameters,
  77. boolean includeDefaultValue,
  78. @Nullable TypeEvalContext context) {
  79. final StringBuilder result = new StringBuilder();
  80. result.append("(");
  81. walkDownParameters(
  82. parameters,
  83. new ParamHelper.ParamWalker() {
  84. @Override
  85. public void enterTupleParameter(PyTupleParameter param, boolean first, boolean last) {
  86. result.append("(");
  87. }
  88. @Override
  89. public void leaveTupleParameter(PyTupleParameter param, boolean first, boolean last) {
  90. result.append(")");
  91. if (!last) result.append(", ");
  92. }
  93. @Override
  94. public void visitNamedParameter(PyNamedParameter param, boolean first, boolean last) {
  95. visitNonPsiParameter(PyCallableParameterImpl.psi(param), first, last);
  96. }
  97. @Override
  98. public void visitSlashParameter(@NotNull PySlashParameter param, boolean first, boolean last) {
  99. result.append('/');
  100. if (!last) result.append(", ");
  101. }
  102. @Override
  103. public void visitSingleStarParameter(PySingleStarParameter param, boolean first, boolean last) {
  104. result.append('*');
  105. if (!last) result.append(", ");
  106. }
  107. @Override
  108. public void visitNonPsiParameter(@NotNull PyCallableParameter parameter, boolean first, boolean last) {
  109. result.append(parameter.getPresentableText(includeDefaultValue, context));
  110. if (!last) result.append(", ");
  111. }
  112. }
  113. );
  114. result.append(")");
  115. return result.toString();
  116. }
  117. @Nullable
  118. public static String getDefaultValueText(@Nullable PyExpression defaultValue) {
  119. if (defaultValue instanceof PyStringLiteralExpression) {
  120. final Pair<String, String> quotes = PyStringLiteralUtil.getQuotes(defaultValue.getText());
  121. if (quotes != null) {
  122. return quotes.getFirst() + ((PyStringLiteralExpression)defaultValue).getStringValue() + quotes.getSecond();
  123. }
  124. }
  125. return defaultValue == null ? null : defaultValue.getText();
  126. }
  127. public interface ParamWalker {
  128. /**
  129. * Is called when a tuple parameter is encountered, before visiting any parameters nested in it.
  130. * @param param the parameter
  131. * @param first true iff it is the first in the list
  132. * @param last true it is the last in the list
  133. */
  134. void enterTupleParameter(PyTupleParameter param, boolean first, boolean last);
  135. /**
  136. * Is called when all nested parameters of a given tuple parameter are visited.
  137. * @param param the parameter
  138. * @param first true iff it is the first in the list
  139. * @param last true it is the last in the list
  140. */
  141. void leaveTupleParameter(PyTupleParameter param, boolean first, boolean last);
  142. /**
  143. * Is called when a named parameter is encountered.
  144. * @param param the parameter
  145. * @param first true iff it is the first in the list
  146. * @param last true it is the last in the list
  147. */
  148. void visitNamedParameter(PyNamedParameter param, boolean first, boolean last);
  149. void visitSlashParameter(@NotNull PySlashParameter param, boolean first, boolean last);
  150. void visitSingleStarParameter(PySingleStarParameter param, boolean first, boolean last);
  151. void visitNonPsiParameter(@NotNull PyCallableParameter parameter, boolean first, boolean last);
  152. }
  153. public static abstract class ParamVisitor implements ParamWalker {
  154. @Override
  155. public void enterTupleParameter(PyTupleParameter param, boolean first, boolean last) { }
  156. @Override
  157. public void leaveTupleParameter(PyTupleParameter param, boolean first, boolean last) { }
  158. @Override
  159. public void visitNamedParameter(PyNamedParameter param, boolean first, boolean last) { }
  160. @Override
  161. public void visitSlashParameter(@NotNull PySlashParameter param, boolean first, boolean last) { }
  162. @Override
  163. public void visitSingleStarParameter(PySingleStarParameter param, boolean first, boolean last) { }
  164. @Override
  165. public void visitNonPsiParameter(@NotNull PyCallableParameter parameter, boolean first, boolean last) { }
  166. }
  167. public static List<PyNamedParameter> collectNamedParameters(PyParameterList plist) {
  168. final List<PyNamedParameter> result = new ArrayList<>(10); // a random 'enough'
  169. walkDownParamArray(
  170. plist.getParameters(),
  171. new ParamVisitor() {
  172. @Override
  173. public void visitNamedParameter(PyNamedParameter param, boolean first, boolean last) {
  174. result.add(param);
  175. }
  176. }
  177. );
  178. return result;
  179. }
  180. }