/******************************************************************************* * Copyright 2015 Software Evolution and Architecture Lab, University of Zurich * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. ******************************************************************************/ package eu.cloudwave.wp5.feedback.eclipse.performance.core.builders.participants; import java.util.Map; import org.eclipse.core.resources.IMarker; import org.eclipse.jdt.core.dom.ASTVisitor; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.MethodInvocation; import com.google.common.collect.Maps; import eu.cloudwave.wp5.common.dto.AggregatedProcedureMetricsDto; import eu.cloudwave.wp5.common.model.Procedure; import eu.cloudwave.wp5.common.model.ProcedureKind; import eu.cloudwave.wp5.common.util.Joiners; import eu.cloudwave.wp5.common.util.TimeValues; import eu.cloudwave.wp5.feedback.eclipse.base.core.builders.participants.AbstractFeedbackBuilderParticipant; import eu.cloudwave.wp5.feedback.eclipse.base.core.builders.participants.FeedbackBuilderParticipant; import eu.cloudwave.wp5.feedback.eclipse.base.infrastructure.template.TemplateHandler; import eu.cloudwave.wp5.feedback.eclipse.base.resources.core.java.FeedbackJavaFile; import eu.cloudwave.wp5.feedback.eclipse.base.resources.core.java.FeedbackJavaProject; import eu.cloudwave.wp5.feedback.eclipse.base.resources.markers.MarkerAttributes; import eu.cloudwave.wp5.feedback.eclipse.base.resources.markers.MarkerPosition; import eu.cloudwave.wp5.feedback.eclipse.base.resources.markers.MarkerSpecification; import eu.cloudwave.wp5.feedback.eclipse.performance.Ids; import eu.cloudwave.wp5.feedback.eclipse.performance.PerformancePluginActivator; import eu.cloudwave.wp5.feedback.eclipse.performance.core.ast.extensions.AbstractMethodExtension; import eu.cloudwave.wp5.feedback.eclipse.performance.core.ast.extensions.MethodDeclarationExtension; import eu.cloudwave.wp5.feedback.eclipse.performance.core.ast.extensions.MethodInvocationExtension; import eu.cloudwave.wp5.feedback.eclipse.performance.core.feedbackhandler.FeedbackHandlerEclipseClient; import eu.cloudwave.wp5.feedback.eclipse.performance.core.markers.PerformanceMarkerTypes; /** * A builder participant that is responsible to display warnings for hotspot procedures. */ public class HotspotsBuilderParticipant extends AbstractFeedbackBuilderParticipant implements FeedbackBuilderParticipant { private static final String AVG_EXECUTION_TIME = "avgExecutionTime"; private static final String NAME = "name"; private static final String KIND = "kind"; private static final String HOTSPOT = "hotspot"; private static final String MESSAGE_PATTERN = "Hotspot %s: Average Execution Time of %s is %s."; private static final String METHOD = "Method"; private static final String CONSTRUCTOR = "Constructor"; private static final int DECIMAL_PLACES = 3; private FeedbackHandlerEclipseClient feedbackHandlerClient; private TemplateHandler templateHandler; public HotspotsBuilderParticipant() { this.feedbackHandlerClient = PerformancePluginActivator.instance(FeedbackHandlerEclipseClient.class); this.templateHandler = PerformancePluginActivator.instance(TemplateHandler.class); } /** * {@inheritDoc} */ @Override protected void buildFile(final FeedbackJavaProject project, final FeedbackJavaFile javaFile, final CompilationUnit astRoot) { // System.out.println("HotspotsBuilderParticipant buildfile"); astRoot.accept(new ASTVisitor() { private AggregatedProcedureMetricsDto[] hotspots; @Override public boolean visit(final MethodDeclaration methodDeclaration) { visit(new MethodDeclarationExtension(methodDeclaration)); return true; } @Override public boolean visit(final MethodInvocation methodInvocation) { visit(new MethodInvocationExtension(methodInvocation)); return true; } private void visit(final AbstractMethodExtension<?> methodExt) { for (final AggregatedProcedureMetricsDto hotspot : getHotspots()) { if (methodExt.correlatesWith(hotspot.getProcedure())) { final int startPosition = methodExt.getStartPosition(); final int line = astRoot.getLineNumber(startPosition); addMarker(javaFile, createMarkerSpecification(new MarkerPosition(line, startPosition, methodExt.getEndPosition()), hotspot)); } } } private AggregatedProcedureMetricsDto[] getHotspots() { if (hotspots == null) { hotspots = feedbackHandlerClient.hotspots(project); } return hotspots; } }); } private MarkerSpecification createMarkerSpecification(final MarkerPosition markerPosition, final AggregatedProcedureMetricsDto hotspot) { final Procedure procedure = hotspot.getProcedure(); final String valueAsText = TimeValues.toText(hotspot.getAverageExecutionTime(), DECIMAL_PLACES); final String kind = procedure.getKind().equals(ProcedureKind.CONSTRUCTOR) ? CONSTRUCTOR : METHOD; final String message = String.format(MESSAGE_PATTERN, kind, procedure.getName(), valueAsText); final Map<String, Object> context = Maps.newHashMap(); context.put(KIND, kind); context.put(NAME, procedure.getName()); context.put(AVG_EXECUTION_TIME, valueAsText); final String description = templateHandler.getContent(HOTSPOT, context); return MarkerSpecification.of(Ids.PERFORMANCE_MARKER, markerPosition, IMarker.SEVERITY_WARNING, PerformanceMarkerTypes.HOTSPOT, message).and(MarkerAttributes.DESCRIPTION, description) .and(MarkerAttributes.CLASS_NAME, procedure.getClassName()).and(MarkerAttributes.PROCEDURE_NAME, procedure.getName()) .and(MarkerAttributes.ARGUMENTS, Joiners.onComma(procedure.getArguments().toArray())); } }