package org.jboss.tools.jsf.ui.test; import java.lang.reflect.InvocationTargetException; import java.util.Iterator; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.Position; import org.eclipse.jface.text.source.IAnnotationModel; import org.eclipse.jface.text.source.SourceViewer; import org.eclipse.jst.jsp.core.internal.validation.JSPActionValidator; import org.eclipse.jst.jsp.core.internal.validation.JSPDirectiveValidator; import org.eclipse.jst.jsp.core.internal.validation.JSPJavaValidator; import org.eclipse.jst.jsp.core.internal.validation.JSPValidator; import org.eclipse.jst.jsp.ui.internal.validation.JSPActionSourceValidator; import org.eclipse.jst.jsp.ui.internal.validation.JSPContentSourceValidator; import org.eclipse.swt.widgets.Display; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorPart; import org.eclipse.ui.IMarkerResolution; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.part.FileEditorInput; import org.eclipse.wst.html.core.internal.validation.HTMLValidator; import org.eclipse.wst.sse.ui.internal.reconcile.TemporaryAnnotation; import org.eclipse.wst.validation.ValidationFramework; import org.eclipse.wst.validation.ValidationResult; import org.eclipse.wst.validation.ValidationState; import org.eclipse.wst.validation.internal.MarkerManager; import org.eclipse.wst.validation.internal.core.Message; import org.eclipse.wst.validation.internal.provisional.core.IMessage; import org.eclipse.wst.validation.internal.provisional.core.IReporter; import org.jboss.tools.common.quickfix.QuickFixManager; import org.jboss.tools.jst.web.ui.internal.editor.jspeditor.JSPMultiPageEditor; import org.jboss.tools.jst.web.ui.action.AddTLDMarkerResolution; import org.jboss.tools.jst.web.ui.action.JSPProblemMarkerResolutionGenerator; import org.jboss.tools.test.util.JobUtils; import org.jboss.tools.tests.AbstractResourceMarkerTest; public class JSPProblemMarkerResolutionTest extends AbstractResourceMarkerTest{ IProject project = null; private static final String JSP_MARKER_TYPE = "org.eclipse.jst.jsp.core.validationMarker"; private static final String XHTML_MARKER_TYPE = "org.eclipse.wst.html.core.validationMarker"; private static final String JSP_EXT = "jsp"; private static final String XHTML_EXT = "xhtml"; private static final int MAX_SECONDS_TO_WAIT = 10; protected final static String EDITOR_ID = "org.jboss.tools.jst.jsp.jspeditor.JSPTextEditor"; //$NON-NLS-1$ public JSPProblemMarkerResolutionTest() { super("JSP Problem Marker Resolution Tests"); } public JSPProblemMarkerResolutionTest(String name) { super(name); } private static boolean isSuspendedValidationDefaultValue; @Override protected void setUp() throws Exception { project = ResourcesPlugin.getWorkspace().getRoot().getProject("test_jsf_project"); isSuspendedValidationDefaultValue = ValidationFramework.getDefault().isSuspended(); ValidationFramework.getDefault().suspendAllValidation(false); //project.refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor()); //project.build(IncrementalProjectBuilder.FULL_BUILD, new NullProgressMonitor()); } public void tearDown() throws Exception { ValidationFramework.getDefault().suspendAllValidation(isSuspendedValidationDefaultValue); } private void validate(IFile file) throws CoreException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException{ MarkerManager manager = MarkerManager.getDefault(); if(JSP_EXT.equals(file.getFileExtension())){ file.deleteMarkers(JSP_MARKER_TYPE, true, IResource.DEPTH_INFINITE); JSPValidator[] validators ={ new JSPContentSourceValidator(), new JSPActionSourceValidator(), new JSPJavaValidator(), new JSPDirectiveValidator() }; for(JSPValidator validator : validators){ ValidationResult result = validator.validate(file, 0, new ValidationState(), new NullProgressMonitor()); IReporter reporter = result.getReporter(new NullProgressMonitor()); List messages = reporter.getMessages(); for(Object m : messages){ if(m instanceof Message){ Message message = (Message)m; IMarker marker = file.createMarker(JSP_MARKER_TYPE); marker.setAttributes(message.getAttributes()); marker.setAttribute(IMarker.MESSAGE, message.getText()); int markerSeverity = IMarker.SEVERITY_INFO; int sev = message.getSeverity(); if ((sev & IMessage.HIGH_SEVERITY) != 0)markerSeverity = IMarker.SEVERITY_ERROR; else if ((sev & IMessage.NORMAL_SEVERITY) != 0)markerSeverity = IMarker.SEVERITY_WARNING; marker.setAttribute(IMarker.SEVERITY, markerSeverity); marker.setAttribute(IMarker.LINE_NUMBER, message.getLineNumber()); marker.setAttribute(IMarker.CHAR_START, message.getOffset()); marker.setAttribute(IMarker.CHAR_END, message.getOffset()+message.getLength()); } } } }else if(XHTML_EXT.equals(file.getFileExtension())){ file.deleteMarkers(XHTML_MARKER_TYPE, true, IResource.DEPTH_INFINITE); // https://issues.jboss.org/browse/JBIDE-11596 compile failed in org.jboss.tools.jsf.ui.test when run against Juno TP // org.eclipse.wst.html.internal.validation.HTMLValidator was moved to org.eclipse.wst.html.core.internal.validation.HTMLValidator // We have to use reflection to be compilable in both Indigo and June. // Class validatorClass = null; // try { // validatorClass = JsfUiPlugin.getDefault().getBundle().loadClass("org.eclipse.wst.html.core.internal.validation.HTMLValidator"); // } catch (ClassNotFoundException e) { // try { // validatorClass = JsfUiPlugin.getDefault().getBundle().loadClass("org.eclipse.wst.html.internal.validation.HTMLValidator"); // } catch (ClassNotFoundException e1) { // fail("Cannot load org.eclipse.wst.html.internal.validation.HTMLValidator (Eclipse Indigo) nor org.eclipse.wst.html.core.internal.validation.HTMLValidator (Eclipse Juno): ClassNotFoundException"); // } // } // Constructor constructor = validatorClass.getConstructor(); // Object validator = constructor.newInstance(); // Method validate = validatorClass.getMethod("validate", IResource.class, int.class, ValidationState.class, IProgressMonitor.class); // ValidationResult result = (ValidationResult)validate.invoke(validator, file, 0, new ValidationState(), new NullProgressMonitor()); HTMLValidator validator = new HTMLValidator(); ValidationResult result = validator.validate(file, 0, new ValidationState(), new NullProgressMonitor()); IReporter reporter = result.getReporter(new NullProgressMonitor()); List<Object> messages = reporter.getMessages(); for(Object m : messages){ if(m instanceof Message){ Message message = (Message)m; IMarker marker = file.createMarker(XHTML_MARKER_TYPE); marker.setAttributes(message.getAttributes()); marker.setAttribute(IMarker.MESSAGE, message.getText()); int markerSeverity = IMarker.SEVERITY_INFO; int sev = message.getSeverity(); if ((sev & IMessage.HIGH_SEVERITY) != 0)markerSeverity = IMarker.SEVERITY_ERROR; else if ((sev & IMessage.NORMAL_SEVERITY) != 0)markerSeverity = IMarker.SEVERITY_WARNING; marker.setAttribute(IMarker.SEVERITY, markerSeverity); marker.setAttribute(IMarker.LINE_NUMBER, message.getLineNumber()); marker.setAttribute(IMarker.CHAR_START, message.getOffset()); marker.setAttribute(IMarker.CHAR_END, message.getOffset()+message.getLength()); } } } } public void testAddTLDMarkerResolutionInJSP() throws CoreException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException { IFile jspFile = project.getFile("WebContent/pages/test_page1.jsp"); assertTrue("File must be exists.",jspFile.exists()); validate(jspFile); assertMarkerIsCreated(jspFile, JSP_MARKER_TYPE, "Unknown tag (h:commandButton).", true, 8); IMarker[] markers = findMarkers(jspFile, JSP_MARKER_TYPE, "Unknown tag (h:commandButton)."); assertEquals("Should be 1 marker here", 1, markers.length); JSPProblemMarkerResolutionGenerator generator = new JSPProblemMarkerResolutionGenerator(); boolean found = false; for(IMarker marker : markers){ generator.hasResolutions(marker); IMarkerResolution[] resolutions = generator.getResolutions(marker); for(IMarkerResolution resolution : resolutions){ resolution.run(marker); found = true; } } assertTrue("AddTLDMarkerResolution not found", found); validate(jspFile); assertMarkerIsNotCreated(jspFile, JSP_MARKER_TYPE, "Unknown tag (h:commandButton)."); } public void testAddAttributeMarkerResolutionInJSP() throws CoreException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException { IFile jspFile = project.getFile("WebContent/pages/test_page2.jsp"); assertTrue("File must be exists.",jspFile.exists()); validate(jspFile); assertMarkerIsCreated(jspFile, JSP_MARKER_TYPE, "Missing required attribute \"select\"", true, 7); IMarker[] markers = findMarkers(jspFile, JSP_MARKER_TYPE, "Missing required attribute \"select\""); assertEquals("Should be 1 marker here", 1, markers.length); JSPProblemMarkerResolutionGenerator generator = new JSPProblemMarkerResolutionGenerator(); boolean found = false; for(IMarker marker : markers){ generator.hasResolutions(marker); IMarkerResolution[] resolutions = generator.getResolutions(marker); for(IMarkerResolution resolution : resolutions){ resolution.run(marker); found = true; } } assertTrue("AddAttributeMarkerResolution not found", found); validate(jspFile); assertMarkerIsNotCreated(jspFile, JSP_MARKER_TYPE, "Missing required attribute \"select\""); } public void testProblemMarkerResolutionInXHTML() throws CoreException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException { IFile jspFile = project.getFile("WebContent/pages/test_page2.xhtml"); assertTrue("File must be exists.",jspFile.exists()); validate(jspFile); assertMarkerIsCreated(jspFile, XHTML_MARKER_TYPE, "Unknown tag (f:loadBundle).", true, 5); IMarker[] markers = findMarkers(jspFile, XHTML_MARKER_TYPE, "Unknown tag (f:loadBundle)."); assertEquals("Should be 1 marker here", 1, markers.length); JSPProblemMarkerResolutionGenerator generator = new JSPProblemMarkerResolutionGenerator(); boolean found = false; for(IMarker marker : markers){ generator.hasResolutions(marker); IMarkerResolution[] resolutions = generator.getResolutions(marker); for(IMarkerResolution resolution : resolutions){ resolution.run(marker); found = true; } } assertTrue("AddTLDMarkerResolution not found", found); validate(jspFile); assertMarkerIsNotCreated(jspFile, XHTML_MARKER_TYPE, "Unknown tag (f:loadBundle)."); } public void testQuickFixesForTemporaryAnnotationInJSP() throws PartInitException, BadLocationException{ checkQuickFixForTemporaryAnnotation("WebContent/pages/test_page3.jsp", 1); } public void testQuickFixesForTemporaryAnnotationInXHTML() throws PartInitException, BadLocationException{ checkQuickFixForTemporaryAnnotation("WebContent/pages/test_page3.xhtml", 5); } private void checkQuickFixForTemporaryAnnotation(String fileName, int lineToDelete) throws PartInitException, BadLocationException{ IFile jspFile = project.getFile(fileName); assertTrue("File not found",jspFile.exists()); IEditorInput input = new FileEditorInput(jspFile); IEditorPart editor = PlatformUI.getWorkbench() .getActiveWorkbenchWindow().getActivePage().openEditor(input, EDITOR_ID, true); if(editor instanceof JSPMultiPageEditor){ JSPMultiPageEditor jspEditor = (JSPMultiPageEditor)editor; SourceViewer viewer = jspEditor.getJspEditor().getTextViewer(); // change file IDocument document = viewer.getDocument(); IRegion region = document.getLineInformation(lineToDelete); document.replace(region.getOffset(), region.getLength(), ""); // Find annotation IAnnotationModel annotationModel = viewer.getAnnotationModel(); TemporaryAnnotation problemAnnotation = waitForProblemAnnotationAppearance(annotationModel, "Unknown tag (", MAX_SECONDS_TO_WAIT); Position position = annotationModel.getPosition(problemAnnotation); assertNotNull("No Unknown tag TemporaryAnnotation found", problemAnnotation); problemAnnotation.setAdditionalFixInfo(document); // get all relevant quick fixes for this annotation if(QuickFixManager.getInstance().hasProposals(problemAnnotation, position)){ List<IJavaCompletionProposal> proposals = QuickFixManager.getInstance().getProposals(problemAnnotation, position); assertTrue("No quick fixes found", proposals.size() > 0); assertEquals("Add tag library definition quick fix not found", AddTLDMarkerResolution.class, proposals.get(0).getClass()); }else{ fail("No quick fixes found"); } }else{ fail("Editor must be instance of JSPMultiPageEditor, was - "+editor.getClass()); } } private TemporaryAnnotation waitForProblemAnnotationAppearance( final IAnnotationModel annotationModel, final String name, final int seconds) { final TemporaryAnnotation[] result = new TemporaryAnnotation[]{null}; Display.getDefault().syncExec(new Runnable() { public void run() { int secondsLeft = seconds; boolean isFirstPass = true; while (secondsLeft-- > 0) { if (!isFirstPass) { JobUtils.delay(1000); // clean deffered events while (Display.getCurrent().readAndDispatch()) ; } else { secondsLeft++; // because the wait step was skipped } //boolean found = false; //IAnnotationModel annotationModel = viewer.getAnnotationModel(); Iterator it = annotationModel.getAnnotationIterator(); while (it.hasNext()) { Object o = it.next(); if (o instanceof TemporaryAnnotation){ if(((TemporaryAnnotation) o).getText().startsWith(name)){ result[0] = (TemporaryAnnotation) o; } } } isFirstPass = false; } } }); return result[0]; } }