private void generateValueValue(final PsiInlineDocTag tag, final StringBuilder buffer, final PsiElement element) { String text = createLinkText(tag.getDataElements()); PsiField valueField = null; if (text.length() == 0) { if (myElement instanceof PsiField) valueField = (PsiField) myElement; } else { PsiElement target = JavaDocUtil.findReferenceTarget(PsiManager.getInstance(myProject), text, myElement); if (target instanceof PsiField) { valueField = (PsiField) target; } } Object value = null; if (valueField != null) { PsiExpression initializer = valueField.getInitializer(); value = JavaConstantExpressionEvaluator.computeConstantExpression(initializer, false); } if (value != null) { buffer.append(value.toString()); } else { buffer.append(element.getText()); } }
@Nullable public DfaValue createValue(PsiExpression psiExpression) { if (psiExpression instanceof PsiReferenceExpression) { return createReferenceValue((PsiReferenceExpression)psiExpression); } if (psiExpression instanceof PsiLiteralExpression) { return createLiteralValue((PsiLiteralExpression)psiExpression); } if (psiExpression instanceof PsiNewExpression) { return getNotNullFactory().create(psiExpression.getType()); } final Object value = JavaConstantExpressionEvaluator.computeConstantExpression(psiExpression, false); PsiType type = psiExpression.getType(); if (value != null && type != null) { if (value instanceof String) { return getNotNullFactory().create(type); // Non-null string literal. } return getConstFactory().createFromValue(value, type, null); } return null; }
@Nullable private PsiVariable getArrayIndexVariable(@Nullable PsiExpression indexExpression) { Object constant = JavaConstantExpressionEvaluator.computeConstantExpression(indexExpression, false); if(constant instanceof Integer) { PsiVariable mockVar = myMockIndices.get(constant); if(mockVar == null) { mockVar = JavaPsiFacade.getElementFactory(indexExpression.getProject()).createField("$array$index$" + constant, PsiType.INT); myMockIndices.put((Integer) constant, mockVar); } return mockVar; } return null; }
public void testConstantEvaluatorStackOverflowResistance() { String text = "class X { String s = \"\" "; for(int i = 0; i < 10000; i++) { text += "+ \"\""; } text += "; }"; PsiJavaFile file = (PsiJavaFile) createDummyFile("a.java", text); PsiExpression expression = file.getClasses()[0].findFieldByName("s", false).getInitializer(); Object o = JavaConstantExpressionEvaluator.computeConstantExpression(expression, false); assertEquals("", o); }
@Override public String checkTagValue(PsiDocTagValue value) { boolean hasReference = (value != null && value.getFirstChild() != null); if (hasReference) { if (!PsiUtil.isLanguageLevel5OrHigher(value)) { return JavaErrorMessages.message("javadoc.value.tag.jdk15.required"); } } if (value != null) { PsiReference reference = value.getReference(); if (reference != null) { PsiElement target = reference.resolve(); if (target != null) { if (!(target instanceof PsiField)) { return JavaErrorMessages.message("javadoc.value.field.required"); } PsiField field = (PsiField) target; if (!field.hasModifierProperty(PsiModifier.STATIC)) { return JavaErrorMessages.message("javadoc.value.static.field.required"); } if (field.getInitializer() == null || JavaConstantExpressionEvaluator.computeConstantExpression(field.getInitializer(), false) == null) { return JavaErrorMessages.message("javadoc.value.field.with.initializer.required"); } } } } return null; }
@Nullable private PsiVariable getArrayIndexVariable(@Nullable PsiExpression indexExpression) { Object constant = JavaConstantExpressionEvaluator.computeConstantExpression(indexExpression, false); if (constant instanceof Integer && ((Integer)constant).intValue() >= 0) { PsiVariable mockVar = myMockIndices.get(constant); if (mockVar == null) { mockVar = JavaPsiFacade.getElementFactory(indexExpression.getProject()).createField("$array$index$" + constant, PsiType.INT); myMockIndices.put((Integer)constant, mockVar); } return mockVar; } return null; }
@Override public int getFlags(PsiElement elementInHost, PsiFile regexp) { final PsiExpressionList list = PsiTreeUtil.getParentOfType(elementInHost, PsiExpressionList.class); if (list != null && list.getExpressions().length == 2 && list.getExpressionTypes()[1] == PsiType.INT) { final Object result = JavaConstantExpressionEvaluator.computeConstantExpression(list.getExpressions()[1], false); if (result instanceof Integer) { //noinspection MagicConstant return ((Integer)result).intValue(); } } return 0; }
private void generateValueValue(final PsiInlineDocTag tag, final StringBuilder buffer, final PsiElement element) { String text = createLinkText(tag.getDataElements()); PsiField valueField = null; if (text.isEmpty()) { if (myElement instanceof PsiField) valueField = (PsiField) myElement; } else { if (text.indexOf('#') == -1) { text = "#" + text; } PsiElement target = JavaDocUtil.findReferenceTarget(PsiManager.getInstance(myProject), text, myElement); if (target instanceof PsiField) { valueField = (PsiField) target; } } Object value = null; if (valueField != null) { PsiExpression initializer = valueField.getInitializer(); value = JavaConstantExpressionEvaluator.computeConstantExpression(initializer, false); } if (value != null) { buffer.append(value); } else { buffer.append(element.getText()); } }
public void testConstantEvaluatorStackOverflowResistance() { String text ="class X { String s = \"\" "; for (int i=0;i<10000;i++) { text += "+ \"\""; } text += "; }"; PsiJavaFile file = (PsiJavaFile)createDummyFile("a.java", text); PsiExpression expression = file.getClasses()[0].findFieldByName("s", false).getInitializer(); Object o = JavaConstantExpressionEvaluator.computeConstantExpression(expression, false); assertEquals("", o); }
private static void checkLiteral(Project project, PsiLiteralExpression expression, List<FoldingDescriptor> result) { if (isI18nProperty(project, expression)) { final IProperty property = getI18nProperty(project, expression); final HashSet<Object> set = new HashSet<Object>(); set.add(property != null ? property : PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT); final String msg = formatI18nProperty(expression, property); final PsiElement parent = expression.getParent(); if (!msg.equals(expression.getText()) && parent instanceof PsiExpressionList && ((PsiExpressionList)parent).getExpressions()[0] == expression) { final PsiExpressionList expressions = (PsiExpressionList)parent; final int count = JavaI18nUtil.getPropertyValueParamsMaxCount(expression); final PsiExpression[] args = expressions.getExpressions(); if (args.length == 1 + count && parent.getParent() instanceof PsiMethodCallExpression) { boolean ok = true; for (int i = 1; i < count + 1; i++) { Object value = JavaConstantExpressionEvaluator.computeConstantExpression(args[i], false); if (value == null) { if (!(args[i] instanceof PsiReferenceExpression)) { ok = false; break; } } } if (ok) { result.add(new FoldingDescriptor(ObjectUtils.assertNotNull(parent.getParent().getNode()), parent.getParent().getTextRange(), null, set)); return; } } } result.add(new FoldingDescriptor(ObjectUtils.assertNotNull(expression.getNode()), expression.getTextRange(), null, set)); } }
private static String formatMethodCallExpression(Project project, PsiMethodCallExpression methodCallExpression) { final PsiExpression[] args = methodCallExpression.getArgumentList().getExpressions(); if (args.length > 0 && args[0] instanceof PsiLiteralExpression && args[0].isValid() && isI18nProperty(project, (PsiLiteralExpression)args[0])) { final int count = JavaI18nUtil.getPropertyValueParamsMaxCount((PsiLiteralExpression)args[0]); if (args.length == 1 + count) { String text = getI18nMessage(project, (PsiLiteralExpression)args[0]); for (int i = 1; i < count + 1; i++) { Object value = JavaConstantExpressionEvaluator.computeConstantExpression(args[i], false); if (value == null) { if (args[i] instanceof PsiReferenceExpression) { value = "{" + args[i].getText() + "}"; } else { text = null; break; } } text = text.replace("{" + (i - 1) + "}", value.toString()); } if (text != null) { if (!text.equals(methodCallExpression.getText())) { text = text.replace("''", "'"); } return text.length() > FOLD_MAX_LENGTH ? text.substring(0, FOLD_MAX_LENGTH - 3) + "...\"" : text; } } } return methodCallExpression.getText(); }
private static void checkLiteral(Project project, PsiLiteralExpression expression, List<FoldingDescriptor> result) { if (isI18nProperty(project, expression)) { final IProperty property = getI18nProperty(project, expression); final HashSet<Object> set = new HashSet<Object>(); set.add(property); final String msg = formatI18nProperty(expression, property); final PsiElement parent = expression.getParent(); if (!msg.equals(expression.getText()) && parent instanceof PsiExpressionList && ((PsiExpressionList)parent).getExpressions()[0] == expression) { final PsiExpressionList expressions = (PsiExpressionList)parent; final int count = JavaI18nUtil.getPropertyValueParamsMaxCount(expression); final PsiExpression[] args = expressions.getExpressions(); if (args.length == 1 + count && parent.getParent() instanceof PsiMethodCallExpression) { boolean ok = true; for (int i = 1; i < count + 1; i++) { Object value = JavaConstantExpressionEvaluator.computeConstantExpression(args[i], false); if (value == null) { if (!(args[i] instanceof PsiReferenceExpression)) { ok = false; break; } } } if (ok) { result.add(new FoldingDescriptor(ObjectUtils.assertNotNull(parent.getParent().getNode()), parent.getParent().getTextRange(), null, set)); return; } } } result.add(new FoldingDescriptor(ObjectUtils.assertNotNull(expression.getNode()), expression.getTextRange(), null, set)); } }
private static String formatMethodCallExpression(Project project, PsiMethodCallExpression methodCallExpression) { final PsiExpression[] args = methodCallExpression.getArgumentList().getExpressions(); if(args.length > 0 && args[0] instanceof PsiLiteralExpression && args[0].isValid() && isI18nProperty(project, (PsiLiteralExpression) args[0])) { final int count = JavaI18nUtil.getPropertyValueParamsMaxCount((PsiLiteralExpression) args[0]); if(args.length == 1 + count) { String text = getI18nMessage(project, (PsiLiteralExpression) args[0]); for(int i = 1; i < count + 1; i++) { Object value = JavaConstantExpressionEvaluator.computeConstantExpression(args[i], false); if(value == null) { if(args[i] instanceof PsiReferenceExpression) { value = "{" + args[i].getText() + "}"; } else { text = null; break; } } text = text.replace("{" + (i - 1) + "}", value.toString()); } if(text != null) { if(!text.equals(methodCallExpression.getText())) { text = text.replace("''", "'"); } return text.length() > FOLD_MAX_LENGTH ? text.substring(0, FOLD_MAX_LENGTH - 3) + "...\"" : text; } } } return methodCallExpression.getText(); }
@Contract("null,_->null") @Nullable public static <T> T computeConstantExpression(@Nullable PsiExpression expression, @NotNull Class<T> expectedType) { expression = ParenthesesUtils.stripParentheses(expression); final Object computed = JavaConstantExpressionEvaluator.computeConstantExpression(expression, false); return ObjectUtils.tryCast(computed, expectedType); }
private static Object getObject(PsiExpression expr) { return JavaConstantExpressionEvaluator.computeConstantExpression(expr, true); }
@Nullable private static Object compute(@NotNull PsiExpression expr) { return JavaConstantExpressionEvaluator.computeConstantExpression(expr, true); }
@NotNull private static String insertArguments(@NotNull PsiMethodCallExpression methodCallExpression, @NotNull String s) { if (s.indexOf('%') == -1) { return s; } final PsiExpression[] args = methodCallExpression.getArgumentList().getExpressions(); if (args.length == 0 || !args[0].isValid()) { return s; } Matcher matcher = FORMAT.matcher(s); int index = 0; int prevIndex = 0; int nextNumber = 1; int start = 0; StringBuilder sb = new StringBuilder(2 * s.length()); while (true) { if (matcher.find(index)) { if ("%".equals(matcher.group(6))) { index = matcher.end(); continue; } int matchStart = matcher.start(); // Make sure this is not an escaped '%' for (; prevIndex < matchStart; prevIndex++) { char c = s.charAt(prevIndex); if (c == '\\') { prevIndex++; } } if (prevIndex > matchStart) { // We're in an escape, ignore this result index = prevIndex; continue; } index = matcher.end(); // Shouldn't throw a number format exception since we've already // matched the pattern in the regexp int number; String numberString = matcher.group(1); if (numberString != null) { // Strip off trailing $ numberString = numberString.substring(0, numberString.length() - 1); number = Integer.parseInt(numberString); nextNumber = number + 1; } else { number = nextNumber++; } if (number > 0 && number < args.length) { PsiExpression argExpression = args[number]; Object value = JavaConstantExpressionEvaluator.computeConstantExpression(argExpression, false); if (value == null) { value = args[number].getText(); } for (int i = start; i < matchStart; i++) { sb.append(s.charAt(i)); } sb.append('{'); sb.append(value); sb.append('}'); start = index; } } else { for (int i = start, n = s.length(); i < n; i++) { sb.append(s.charAt(i)); } break; } } return sb.toString(); }
@Nullable public DfaValue getExpressionDfaValue(@Nullable PsiExpression expression) { if(expression == null) { return null; } if(expression instanceof PsiParenthesizedExpression) { return getExpressionDfaValue(((PsiParenthesizedExpression) expression).getExpression()); } if(expression instanceof PsiArrayAccessExpression) { PsiExpression arrayExpression = ((PsiArrayAccessExpression) expression).getArrayExpression(); DfaValue qualifier = getExpressionDfaValue(arrayExpression); if(qualifier instanceof DfaVariableValue) { PsiVariable indexVar = getArrayIndexVariable(((PsiArrayAccessExpression) expression).getIndexExpression()); if(indexVar != null) { return myFactory.getVarFactory().createVariableValue(indexVar, expression.getType(), false, (DfaVariableValue) qualifier); } } return null; } if(expression instanceof PsiMethodCallExpression) { return createReferenceValue(((PsiMethodCallExpression) expression).getMethodExpression()); } if(expression instanceof PsiReferenceExpression) { return createReferenceValue((PsiReferenceExpression) expression); } if(expression instanceof PsiLiteralExpression) { return myFactory.createLiteralValue((PsiLiteralExpression) expression); } if(expression instanceof PsiNewExpression) { return myFactory.createTypeValue(expression.getType(), Nullness.NOT_NULL); } final Object value = JavaConstantExpressionEvaluator.computeConstantExpression(expression, false); PsiType type = expression.getType(); if(value != null && type != null) { if(value instanceof String) { return myFactory.createTypeValue(type, Nullness.NOT_NULL); // Non-null string literal. } return myFactory.getConstFactory().createFromValue(value, type, null); } return null; }
private static void checkLiteral(Project project, PsiLiteralExpression expression, List<FoldingDescriptor> result) { if(isI18nProperty(project, expression)) { final IProperty property = getI18nProperty(project, expression); final HashSet<Object> set = new HashSet<Object>(); set.add(property != null ? property : PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT); final String msg = formatI18nProperty(expression, property); final PsiElement parent = expression.getParent(); if(!msg.equals(expression.getText()) && parent instanceof PsiExpressionList && ((PsiExpressionList) parent).getExpressions()[0] == expression) { final PsiExpressionList expressions = (PsiExpressionList) parent; final int count = JavaI18nUtil.getPropertyValueParamsMaxCount(expression); final PsiExpression[] args = expressions.getExpressions(); if(args.length == 1 + count && parent.getParent() instanceof PsiMethodCallExpression) { boolean ok = true; for(int i = 1; i < count + 1; i++) { Object value = JavaConstantExpressionEvaluator.computeConstantExpression(args[i], false); if(value == null) { if(!(args[i] instanceof PsiReferenceExpression)) { ok = false; break; } } } if(ok) { result.add(new FoldingDescriptor(ObjectUtils.assertNotNull(parent.getParent().getNode()), parent.getParent().getTextRange(), null, set)); return; } } } result.add(new FoldingDescriptor(ObjectUtils.assertNotNull(expression.getNode()), expression.getTextRange(), null, set)); } }
private void generateValueValue(final PsiInlineDocTag tag, final StringBuilder buffer, final PsiElement element) { String text = createLinkText(tag.getDataElements()); PsiField valueField = null; if(text.isEmpty()) { if(myElement instanceof PsiField) { valueField = (PsiField) myElement; } } else { if(text.indexOf('#') == -1) { text = "#" + text; } PsiElement target = JavaDocUtil.findReferenceTarget(PsiManager.getInstance(myProject), text, myElement); if(target instanceof PsiField) { valueField = (PsiField) target; } } Object value = null; if(valueField != null) { PsiExpression initializer = valueField.getInitializer(); value = JavaConstantExpressionEvaluator.computeConstantExpression(initializer, false); } if(value != null) { String valueText = StringUtil.escapeXml(value.toString()); if(value instanceof String) { valueText = '"' + valueText + '"'; } if(valueField.equals(myElement)) { buffer.append(valueText); // don't generate link to itself } else { generateLink(buffer, valueField, valueText, true); } } else { buffer.append(element.getText()); } }