/** * Copyright (c) 2015 Codetrails GmbH. 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: Simon Laffoy - initial API and implementation. */ package org.eclipse.recommenders.testing.rcp.completion.rules; import static java.io.File.separator; import static org.eclipse.recommenders.testing.jdt.AstUtils.MARKER; import static org.eclipse.recommenders.testing.rcp.completion.rules.TemporaryProject.SRC_FOLDER_NAME; import static org.eclipse.recommenders.utils.Checks.ensureIsTrue; import static org.eclipse.recommenders.utils.Pair.newPair; import static org.junit.Assert.assertTrue; import java.io.ByteArrayInputStream; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.ui.JavaUI; import org.eclipse.jdt.ui.SharedASTProvider; import org.eclipse.jdt.ui.text.java.JavaContentAssistInvocationContext; import org.eclipse.recommenders.completion.rcp.IRecommendersCompletionContext; import org.eclipse.recommenders.completion.rcp.RecommendersCompletionContext; import org.eclipse.recommenders.internal.rcp.CachingAstProvider; import org.eclipse.recommenders.testing.rcp.jdt.JavaContentAssistContextMock; import org.eclipse.recommenders.utils.Constants; import org.eclipse.recommenders.utils.Pair; import com.google.common.collect.Sets; @SuppressWarnings("restriction") public class TemporaryFile { private static final String JAVA_IDENTIFIER_REGEX = "([a-zA-Z_$\\p{Lu}\\p{Ll}]{1}" + "[a-zA-Z_$0-9\\p{Lu}\\p{Ll}\\p{Nl}]*)"; private final ICompilationUnit cu; private final Set<Integer> markers; private final TemporaryProject tempProject; TemporaryFile(TemporaryProject parentProject, CharSequence code) throws CoreException { this.tempProject = parentProject; Pair<ICompilationUnit, Set<Integer>> struct = createFileAndParseWithMarkers(code); this.cu = struct.getFirst(); this.markers = struct.getSecond(); } public CompilationUnit getAst() { return SharedASTProvider.getAST(cu, SharedASTProvider.WAIT_YES, null); } public IRecommendersCompletionContext triggerContentAssist() throws JavaModelException { JavaContentAssistInvocationContext javaContext = new JavaContentAssistContextMock(cu, markers.iterator().next()); return new RecommendersCompletionContext(javaContext, new CachingAstProvider()); } private Pair<ICompilationUnit, Set<Integer>> createFileAndParseWithMarkers(final CharSequence contentWithMarkers) throws CoreException { final Pair<String, Set<Integer>> content = findMarkers(contentWithMarkers, MARKER); final ICompilationUnit cu = createFile(content.getFirst()); tempProject.refreshAndBuildProject(); return Pair.newPair(cu, content.getSecond()); } private Pair<String, Set<Integer>> findMarkers(final CharSequence content, String marker) { final Set<Integer> markers = Sets.newTreeSet(); int pos = 0; final StringBuilder sb = new StringBuilder(content); while ((pos = sb.indexOf(marker, pos)) != -1) { sb.deleteCharAt(pos); markers.add(pos); ensureIsTrue(pos <= sb.length()); pos--; } return newPair(sb.toString(), markers); } private ICompilationUnit createFile(final String content) throws CoreException { // get filename final String fileName = findClassName(content) + Constants.DOT_JAVA; // add the file name and get the file StringBuilder projectRelativeFilePath = new StringBuilder(); projectRelativeFilePath.append(SRC_FOLDER_NAME); projectRelativeFilePath.append(separator); projectRelativeFilePath.append(fileName); final IPath projectRelativePath = new Path(projectRelativeFilePath.toString()); final IFile file = tempProject.getProject().getFile(projectRelativePath); // delete file if (file.exists()) { file.delete(true, null); } // create file final ByteArrayInputStream is = new ByteArrayInputStream(content.getBytes()); file.create(is, true, null); int attempts = 0; while (!file.exists()) { try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } attempts++; if (attempts > 10) { throw new IllegalStateException("Failed to create file"); } } IJavaProject javaProject = tempProject.getJavaProject(); if (javaProject == null) { throw new IllegalStateException("The temporaryProject does not yet have an associated IJavaProject."); } // get the compilation unit Path srcRelativePath = new Path(fileName); ICompilationUnit cu = (ICompilationUnit) javaProject.findElement(srcRelativePath); while (cu == null) { cu = (ICompilationUnit) javaProject.findElement(srcRelativePath); } return cu; } public void openFileInEditor() throws CoreException { JavaUI.openInEditor(cu); } private static String findClassName(final CharSequence source) { Pattern p = Pattern.compile(".*?class\\s+" + JAVA_IDENTIFIER_REGEX + ".*", Pattern.DOTALL); Matcher matcher = p.matcher(source); if (!matcher.matches()) { p = Pattern.compile(".*interface\\s+" + JAVA_IDENTIFIER_REGEX + ".*", Pattern.DOTALL); matcher = p.matcher(source); } assertTrue(matcher.matches()); return matcher.group(1); } }