/* * Copyright 2016 Nokia Solutions and Networks * Licensed under the Apache License, Version 2.0, * see license.txt file for details. */ package org.robotframework.ide.eclipse.main.plugin.project.build.fix; import java.io.File; import java.io.IOException; import java.util.Arrays; import java.util.List; import java.util.Optional; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.rf.ide.core.project.ImportPath; import org.rf.ide.core.project.ResolvedImportPath; import org.robotframework.ide.eclipse.main.plugin.model.RobotSuiteFile; import org.robotframework.ide.eclipse.main.plugin.project.build.AdditionalMarkerAttributes; import com.google.common.annotations.VisibleForTesting; /** * @author Lukasz Wlodarczyk */ public class CreateResourceFileFixer extends RedSuiteMarkerResolution { private final Optional<ICompletionProposal> proposal; private final String label; public static CreateResourceFileFixer createFixer(final String nonExistingFile, final IMarker marker) { final IPath pathToCreate = getValidPathToCreate(marker); if (pathToCreate == null || !isExtensionValid(pathToCreate.getFileExtension())) { return new CreateResourceFileFixer(CreateResourceFileFixer.createEmptyProposal(), "Missing resource file cannot be auto-created"); } else { return new CreateResourceFileFixer( CreateResourceFileFixer.createProposal(marker, pathToCreate, nonExistingFile), "Create missing " + nonExistingFile + " file"); } } @VisibleForTesting static IPath getValidPathToCreate(final IMarker marker) { final String srcPath = marker.getAttribute(AdditionalMarkerAttributes.PATH, null); final File file = new File(srcPath); try { file.getCanonicalPath(); } catch (final IOException e) { return null; } final IPath fullPath = new Path(ResolvedImportPath.from(ImportPath.from(srcPath)) .get() .resolveInRespectTo(marker.getResource().getLocationURI()) .toString()); final IPath workspaceDir = new Path(marker.getResource().getWorkspace().getRoot().getLocationURI().toString()); if (workspaceDir.matchingFirstSegments(fullPath) != workspaceDir.segmentCount()) { return null; } final IPath pathToCreate = new Path(ResolvedImportPath .reverseUriSpecialCharsEscapes(fullPath.removeFirstSegments(workspaceDir.segmentCount()).toString())); if (pathToCreate == null || pathToCreate.segmentCount() < 2 || !ResourcesPlugin.getWorkspace().getRoot().getProject(pathToCreate.segment(0)).isAccessible() || !pathToCreate.isValidPath(pathToCreate.toPortableString())) { return null; } else { return pathToCreate; } } // this method should be implemented elsewhere private static boolean isExtensionValid(final String extension) { final List<String> validExts = Arrays .asList(new String[] { "html", "htm", "xhtml", "tsv", "txt", "rst", "robot", "rest" }); return extension != null && validExts.contains(extension.toLowerCase()); } public CreateResourceFileFixer(final Optional<ICompletionProposal> proposal, final String label) { this.proposal = proposal; this.label = label; } @Override public String getLabel() { return label; } @Override public Optional<ICompletionProposal> asContentProposal(final IMarker marker, final IDocument document, final RobotSuiteFile suiteModel) { return proposal; } private static Optional<ICompletionProposal> createProposal(final IMarker marker, final IPath path, final String res) { final MissingResourceFileCompletionProposal proposal = new MissingResourceFileCompletionProposal( "Create missing " + res + " file", "<b>" + res + "</b><br> file will be created and opened for edition.<br><br>Resource path must be valid, " + "inside project directory and must include robot resource extension. Any missing parent directories will be also created.", marker, path); return Optional.<ICompletionProposal> of(proposal); } private static Optional<ICompletionProposal> createEmptyProposal() { final EmptyCompletionProposal proposal = new EmptyCompletionProposal("Missing resource file cannot be auto-created", "Please check your file path if you want to use this Quick Fix." + "<br>Only valid and legal path to the file with explicit robot resource extension " + "inside existing open project in this workspace can be used." + "<br>All missing parent directories inside project will be auto-generated."); return Optional.<ICompletionProposal> of(proposal); } }