<commit_before>/*******************************************************************************
 * Copyright (c) 2017 Pivotal, Inc.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Pivotal, Inc. - initial API and implementation
 *******************************************************************************/
package org.springframework.ide.vscode.boot.java.conditionals;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;

import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.lsp4j.Hover;
import org.eclipse.lsp4j.MarkedString;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.ide.vscode.boot.java.handlers.HoverProvider;
import org.springframework.ide.vscode.commons.boot.app.cli.SpringBootApp;
import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.Log;
import org.springframework.ide.vscode.commons.util.text.TextDocument;

import com.google.common.collect.ImmutableList;

/**
 *
 * Provides live hovers and hints for @ConditionalOn... Spring Boot annotations
 * from running spring boot apps.
 */
public class ConditionalsLiveHoverProvider implements HoverProvider {

	@Override
	public CompletableFuture<Hover> provideHover(ASTNode node, Annotation annotation, ITypeBinding type, int offset,
			TextDocument doc, SpringBootApp[] runningApps) {
		return provideHover(annotation, doc, runningApps);
	}

	@Override
	public Collection<Range> getLiveHoverHints(Annotation annotation, TextDocument doc, SpringBootApp[] runningApps) {
		try {
			if (runningApps.length > 0) {
				ConditionalParserFromRunningApp parser = new ConditionalParserFromRunningApp();
				Optional<List<RunningAppConditional>> val = parser.parse(annotation, runningApps);
				if (val.isPresent()) {
					Range hoverRange = doc.toRange(annotation.getStartPosition(), annotation.getLength());
					return ImmutableList.of(hoverRange);
				}
			}
		} catch (BadLocationException e) {
			Log.log(e);
		}

		return null;
	}

	private CompletableFuture<Hover> provideHover(Annotation annotation, TextDocument doc,
			SpringBootApp[] runningApps) {

		try {
			List<Either<String, MarkedString>> hoverContent = new ArrayList<>();
			ConditionalParserFromRunningApp parser = new ConditionalParserFromRunningApp();
			Optional<List<RunningAppConditional>> val = parser.parse(annotation, runningApps);

			if (val.isPresent()) {
				addHoverContent(val.get(), hoverContent);
			}

			Range hoverRange = doc.toRange(annotation.getStartPosition(), annotation.getLength());
			Hover hover = new Hover();

			hover.setContents(hoverContent);
			hover.setRange(hoverRange);

			return CompletableFuture.completedFuture(hover);
		} catch (Exception e) {
			Log.log(e);
		}

		return null;
	}

	private void addHoverContent(List<RunningAppConditional> conditions,
			List<Either<String, MarkedString>> hoverContent) throws Exception {
		for (int i = 0; i < conditions.size(); i++) {
			RunningAppConditional condition = conditions.get(i);
			hoverContent.add(Either.forLeft("Condition: " + condition.condition));
			hoverContent.add(Either.forLeft("Message: " + condition.message));
			hoverContent.add(Either
					.forLeft("Process " + condition.app.getProcessID() + ": " + condition.app.getProcessName()));

			if (i < conditions.size() - 1) {
				hoverContent.add(Either.forLeft("---"));
			}
		}
	}

	/**
	 * Parsers @ConditionalOn annotations from a spring boot running app's
	 * autoconfig report. An example of a conditional that is parsed from a running
	 * app's autoconfig report would be:
	 *
	 * {"TraceRepositoryAutoConfiguration#traceRepository":[{"condition":"OnBeanCondition","message":"@ConditionalOnMissingBean
	 * (types: org.springframework.boot.actuate.trace.TraceRepository;
	 * SearchStrategy: all) did not find any beans"}]
	 *
	 */
	public static class ConditionalParserFromRunningApp {

		public Optional<List<RunningAppConditional>> parse(Annotation annotation, SpringBootApp[] runningApps) {

			try {
				List<RunningAppConditional> allConditionals = new ArrayList<>();
				for (SpringBootApp app : runningApps) {
					String autoConfigRecord = app.getAutoConfigReport();
					if (autoConfigRecord != null) {<commit_msg>Reduce conditional message to one line<commit_after>/*******************************************************************************
 * Copyright (c) 2017 Pivotal, Inc.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Pivotal, Inc. - initial API and implementation
 *******************************************************************************/
package org.springframework.ide.vscode.boot.java.conditionals;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;

import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.lsp4j.Hover;
import org.eclipse.lsp4j.MarkedString;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.ide.vscode.boot.java.handlers.HoverProvider;
import org.springframework.ide.vscode.commons.boot.app.cli.SpringBootApp;
import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.Log;
import org.springframework.ide.vscode.commons.util.text.TextDocument;

import com.google.common.collect.ImmutableList;

/**
 *
 * Provides live hovers and hints for @ConditionalOn... Spring Boot annotations
 * from running spring boot apps.
 */
public class ConditionalsLiveHoverProvider implements HoverProvider {

	@Override
	public CompletableFuture<Hover> provideHover(ASTNode node, Annotation annotation, ITypeBinding type, int offset,
			TextDocument doc, SpringBootApp[] runningApps) {
		return provideHover(annotation, doc, runningApps);
	}

	@Override
	public Collection<Range> getLiveHoverHints(Annotation annotation, TextDocument doc, SpringBootApp[] runningApps) {
		try {
			if (runningApps.length > 0) {
				ConditionalParserFromRunningApp parser = new ConditionalParserFromRunningApp();
				Optional<List<RunningAppConditional>> val = parser.parse(annotation, runningApps);
				if (val.isPresent()) {
					Range hoverRange = doc.toRange(annotation.getStartPosition(), annotation.getLength());
					return ImmutableList.of(hoverRange);
				}
			}
		} catch (BadLocationException e) {
			Log.log(e);
		}

		return null;
	}

	private CompletableFuture<Hover> provideHover(Annotation annotation, TextDocument doc,
			SpringBootApp[] runningApps) {

		try {
			List<Either<String, MarkedString>> hoverContent = new ArrayList<>();
			ConditionalParserFromRunningApp parser = new ConditionalParserFromRunningApp();
			Optional<List<RunningAppConditional>> val = parser.parse(annotation, runningApps);

			if (val.isPresent()) {
				addHoverContent(val.get(), hoverContent);
			}

			Range hoverRange = doc.toRange(annotation.getStartPosition(), annotation.getLength());
			Hover hover = new Hover();

			hover.setContents(hoverContent);
			hover.setRange(hoverRange);

			return CompletableFuture.completedFuture(hover);
		} catch (Exception e) {
			Log.log(e);
		}

		return null;
	}

	private void addHoverContent(List<RunningAppConditional> conditions,
			List<Either<String, MarkedString>> hoverContent) throws Exception {
		for (int i = 0; i < conditions.size(); i++) {
			RunningAppConditional condition = conditions.get(i);
			hoverContent.add(Either.forLeft(condition.message));
			hoverContent.add(Either
					.forLeft("Process " + condition.app.getProcessID() + ": " + condition.app.getProcessName()));

			if (i < conditions.size() - 1) {
				hoverContent.add(Either.forLeft("---"));
			}
		}
	}

	/**
	 * Parsers @ConditionalOn annotations from a spring boot running app's
	 * autoconfig report. An example of a conditional that is parsed from a running
	 * app's autoconfig report would be:
	 *
	 * {"TraceRepositoryAutoConfiguration#traceRepository":[{"condition":"OnBeanCondition","message":"@ConditionalOnMissingBean
	 * (types: org.springframework.boot.actuate.trace.TraceRepository;
	 * SearchStrategy: all) did not find any beans"}]
	 *
	 */
	public static class ConditionalParserFromRunningApp {

		public Optional<List<RunningAppConditional>> parse(Annotation annotation, SpringBootApp[] runningApps) {

			try {
				List<RunningAppConditional> allConditionals = new ArrayList<>();
				for (SpringBootApp app : runningApps) {
					String autoConfigRecord = app.getAutoConfigReport();
					if (autoConfigRecord != null) {
{'fraction_non_alphanumeric': 0.1399320917789896, 'fraction_numerical': 0.0030867373186541825, 'mean_word_length': 5.242774566473988, 'pattern_counts': {'":': 8, '<': 41, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2899653', 'n_tokens_mistral': 3059, 'n_tokens_neox': 2728, 'n_words': 612}