diff --git a/codan/org.eclipse.cdt.codan.checkers.ui.test/.classpath b/codan/org.eclipse.cdt.codan.checkers.ui.test/.classpath new file mode 100644 index 00000000000..eca7bdba8f0 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.checkers.ui.test/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/codan/org.eclipse.cdt.codan.checkers.ui.test/.project b/codan/org.eclipse.cdt.codan.checkers.ui.test/.project new file mode 100644 index 00000000000..031b00c6527 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.checkers.ui.test/.project @@ -0,0 +1,28 @@ + + + org.eclipse.cdt.codan.checkers.ui.test + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/codan/org.eclipse.cdt.codan.checkers.ui.test/.settings/org.eclipse.jdt.core.prefs b/codan/org.eclipse.cdt.codan.checkers.ui.test/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 00000000000..0c68a61dca8 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.checkers.ui.test/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,7 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 diff --git a/codan/org.eclipse.cdt.codan.checkers.ui.test/META-INF/MANIFEST.MF b/codan/org.eclipse.cdt.codan.checkers.ui.test/META-INF/MANIFEST.MF new file mode 100644 index 00000000000..6c8e44c7604 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.checkers.ui.test/META-INF/MANIFEST.MF @@ -0,0 +1,23 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: %Bundle-Name +Bundle-SymbolicName: org.eclipse.cdt.codan.checkers.ui.test +Bundle-Version: 3.2.0.qualifier +Bundle-Activator: org.eclipse.cdt.codan.checkers.ui.Activator +Require-Bundle: org.eclipse.core.runtime, + org.eclipse.cdt.codan.checkers.ui, + org.eclipse.core.resources, + org.eclipse.cdt.codan.ui, + org.eclipse.cdt.codan.ui.cxx, + org.eclipse.ui, + org.eclipse.ui.ide, + org.junit, + org.mockito, + org.hamcrest, + org.eclipse.cdt.core, + org.eclipse.jface.text, + org.eclipse.ui.workbench.texteditor, + org.eclipse.ui.editors +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Bundle-ActivationPolicy: lazy +Bundle-Vendor: %Bundle-Vendor diff --git a/codan/org.eclipse.cdt.codan.checkers.ui.test/OSGI-INF/l10n/bundle.properties b/codan/org.eclipse.cdt.codan.checkers.ui.test/OSGI-INF/l10n/bundle.properties new file mode 100644 index 00000000000..c796fcf3c02 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.checkers.ui.test/OSGI-INF/l10n/bundle.properties @@ -0,0 +1,13 @@ +############################################################################### +# Copyright (c) 2016 COSEDA Technologies GmbH and others. +# 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: +# Dominic Scharfe (COSEDA Technologies GmbH) - initial API and implementation +############################################################################### +#Properties file for org.eclipse.cdt.codan.checkers.ui +Bundle-Vendor = Eclipse CDT +Bundle-Name = Codan Checkers UI Tests diff --git a/codan/org.eclipse.cdt.codan.checkers.ui.test/build.properties b/codan/org.eclipse.cdt.codan.checkers.ui.test/build.properties new file mode 100644 index 00000000000..34d2e4d2dad --- /dev/null +++ b/codan/org.eclipse.cdt.codan.checkers.ui.test/build.properties @@ -0,0 +1,4 @@ +source.. = src/ +output.. = bin/ +bin.includes = META-INF/,\ + . diff --git a/codan/org.eclipse.cdt.codan.checkers.ui.test/pom.xml b/codan/org.eclipse.cdt.codan.checkers.ui.test/pom.xml new file mode 100644 index 00000000000..8920e5cad8b --- /dev/null +++ b/codan/org.eclipse.cdt.codan.checkers.ui.test/pom.xml @@ -0,0 +1,39 @@ + + + 4.0.0 + + + org.eclipse.cdt + cdt-parent + 9.1.0-SNAPSHOT + ../../pom.xml + + + 3.2.0-SNAPSHOT + org.eclipse.cdt.codan.checkers.ui.test + eclipse-test-plugin + + + + + org.eclipse.tycho + tycho-surefire-plugin + ${tycho-version} + + + true + ${tycho.testArgLine} ${base.ui.test.vmargs} + true + + + org.eclipse.platform.feature.group + p2-installable-unit + + + + + + + diff --git a/codan/org.eclipse.cdt.codan.checkers.ui.test/src/org/eclipse/cdt/codan/checkers/ui/Activator.java b/codan/org.eclipse.cdt.codan.checkers.ui.test/src/org/eclipse/cdt/codan/checkers/ui/Activator.java new file mode 100644 index 00000000000..928d0408ae9 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.checkers.ui.test/src/org/eclipse/cdt/codan/checkers/ui/Activator.java @@ -0,0 +1,41 @@ +/******************************************************************************* + * Copyright (c) 2016 COSEDA Technologies 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: + * Dominic Scharfe (COSEDA Technologies GmbH) - initial implementation + * + *******************************************************************************/ +package org.eclipse.cdt.codan.checkers.ui; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +public class Activator implements BundleActivator { + + private static BundleContext context; + + static BundleContext getContext() { + return context; + } + + /* + * (non-Javadoc) + * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext) + */ + public void start(BundleContext bundleContext) throws Exception { + Activator.context = bundleContext; + } + + /* + * (non-Javadoc) + * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext) + */ + public void stop(BundleContext bundleContext) throws Exception { + Activator.context = null; + } + +} diff --git a/codan/org.eclipse.cdt.codan.checkers.ui.test/src/org/eclipse/cdt/codan/checkers/ui/quickfix/QuickFixCreateNewClassTest.java b/codan/org.eclipse.cdt.codan.checkers.ui.test/src/org/eclipse/cdt/codan/checkers/ui/quickfix/QuickFixCreateNewClassTest.java new file mode 100644 index 00000000000..687f1fd7884 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.checkers.ui.test/src/org/eclipse/cdt/codan/checkers/ui/quickfix/QuickFixCreateNewClassTest.java @@ -0,0 +1,126 @@ +/******************************************************************************* + * Copyright (c) 2016 COSEDA Technologies 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: + * Dominic Scharfe (COSEDA Technologies GmbH) - initial implementation + * + *******************************************************************************/ +package org.eclipse.cdt.codan.checkers.ui.quickfix; + +import static org.junit.Assert.*; + +import org.eclipse.cdt.codan.internal.checkers.ui.quickfix.QuickFixCreateNewClass; +import org.eclipse.cdt.codan.ui.AbstractCodanCMarkerResolution; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import static org.mockito.Mockito.*; + +import java.util.function.Function; + +import org.eclipse.cdt.core.dom.ILinkage; +import org.eclipse.cdt.core.model.ILanguage; +import org.eclipse.cdt.core.model.ITranslationUnit; + +@RunWith(MockitoJUnitRunner.class) +public class QuickFixCreateNewClassTest { + + QuickFixCreateNewClass qut; + + @Mock + IMarker marker; + + /** + * TranslationUnit of the marker's resource which is received from the + * workspace. + */ + @Mock + ITranslationUnit translationUnitViaWorkspace; + + /** + * TranslationUnit of the marker's resource if there is an open editor. + */ + @Mock + ITranslationUnit translationUnitWorkingCopy; + + /** + * Function to get the working copy of translationUnitViaWorkspace + */ + @Mock + Function toWorkingCopy; + + /** + * Language of the TranslationUnit + */ + @Mock + ILanguage translationUnitLanguage; + + @Before + public void setUp() throws Exception { + qut = new QuickFixCreateNewClass(toWorkingCopy) { + @Override + protected ITranslationUnit getTranslationUnitViaWorkspace(IMarker marker) { + if (QuickFixCreateNewClassTest.this.marker == marker) { + return translationUnitViaWorkspace; + } + throw new RuntimeException("Invalid marker"); + }; + }; + + when(toWorkingCopy.apply(translationUnitViaWorkspace)).thenReturn(translationUnitWorkingCopy); + when(translationUnitWorkingCopy.getLanguage()).thenReturn(translationUnitLanguage); + } + + /** + * Test if the marker is applicable if + * {@link AbstractCodanCMarkerResolution#getTranslationUnitViaWorkspace} + * returns null. + */ + @Test + public void isApplicableForUnresolvableMarker() { + translationUnitViaWorkspace = null; + assertTrue("Unresolvable marker is not applicable", qut.isApplicable(marker)); + } + + /** + * Test if the marker is applicable if + * {@link AbstractCodanCMarkerResolution#getTranslationUnitViaWorkspace} + * returns a marker valid marker. + */ + @Test + public void isApplicableForResolvableMarker() { + assertTrue("Resolvable marker is not applicable", qut.isApplicable(marker)); + } + + /** + * Test if the marker is applicable if + * tu.getLanguage().getLinkageID() == ILinkage.C_LINKAGE_ID + */ + @Test + public void isNotApplicableForResolvableMarkerWithCLinkage() { + when(translationUnitLanguage.getLinkageID()).thenReturn(ILinkage.C_LINKAGE_ID); + assertFalse("Resolvable marker with ILinkage.C_LINKAGE_ID must not be applicable", qut.isApplicable(marker)); + } + + /** + * Test if the marker is applicable if tu.getLanguage() throws + * a {@link CoreException}. + * + * @throws CoreException + */ + @Test + public void isApplicableForResolvableMarkerWithCLinkageResolutionCoreException() throws CoreException { + CoreException coreException = new CoreException(mock(IStatus.class)); + doThrow(coreException).when(translationUnitWorkingCopy).getLanguage(); + assertTrue("Resolvable marker with invalid language must be applicable", qut.isApplicable(marker)); + } +} diff --git a/codan/org.eclipse.cdt.codan.checkers.ui/META-INF/MANIFEST.MF b/codan/org.eclipse.cdt.codan.checkers.ui/META-INF/MANIFEST.MF index 62aa6c037e1..ae0d4e02558 100644 --- a/codan/org.eclipse.cdt.codan.checkers.ui/META-INF/MANIFEST.MF +++ b/codan/org.eclipse.cdt.codan.checkers.ui/META-INF/MANIFEST.MF @@ -20,5 +20,5 @@ Bundle-ActivationPolicy: lazy Bundle-RequiredExecutionEnvironment: JavaSE-1.8 Bundle-Vendor: %Bundle-Vendor Export-Package: org.eclipse.cdt.codan.internal.checkers.ui;x-internal:=true, - org.eclipse.cdt.codan.internal.checkers.ui.quickfix;x-internal:=true + org.eclipse.cdt.codan.internal.checkers.ui.quickfix;x-friends:="org.eclipse.cdt.codan.checkers.ui.test" diff --git a/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixCreateNewClass.java b/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixCreateNewClass.java index 0907027dc77..605484d03d8 100644 --- a/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixCreateNewClass.java +++ b/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixCreateNewClass.java @@ -8,15 +8,20 @@ * Contributors: * Alena Laskavaia - initial API and implementation, * inspired by work of Erik Johansson + * Dominic Scharfe (COSEDA Technologies GmbH) - Fix for bug 507148 * *******************************************************************************/ package org.eclipse.cdt.codan.internal.checkers.ui.quickfix; +import java.util.Optional; +import java.util.function.Function; + import org.eclipse.cdt.codan.internal.checkers.ui.CheckersUiActivator; import org.eclipse.cdt.codan.ui.AbstractCodanCMarkerResolution; import org.eclipse.cdt.core.dom.ILinkage; import org.eclipse.cdt.core.model.ICElement; import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.internal.corext.util.CModelUtil; import org.eclipse.cdt.internal.ui.wizards.NewClassCreationWizard; import org.eclipse.cdt.ui.CDTSharedImages; import org.eclipse.core.resources.IMarker; @@ -31,6 +36,27 @@ import org.eclipse.ui.IMarkerResolution2; import org.eclipse.ui.PlatformUI; public class QuickFixCreateNewClass extends AbstractCodanCMarkerResolution implements IMarkerResolution2 { + /** + * Returns the working copy TU of the given TU. If the TU is already a + * working copy or the TU has no working copy the input TU is returned. + */ + private final Function toWorkingCopy; + + /** + * Default constructor. + * Uses {@link CModelUtil#toWorkingCopy(ITranslationUnit)} to get the + * working copy of a {@link ITranslationUnit}. + * + * TODO: Inject {@link #toWorkingCopy} as a dependency. + */ + public QuickFixCreateNewClass() { + this(tu -> CModelUtil.toWorkingCopy(tu)); + } + + public QuickFixCreateNewClass(Function toWorkingCopy) { + this.toWorkingCopy = toWorkingCopy; + } + @Override public String getLabel() { // TODO Should provide class name as message parameter @@ -39,14 +65,26 @@ public class QuickFixCreateNewClass extends AbstractCodanCMarkerResolution imple @Override public boolean isApplicable(IMarker marker) { - ITranslationUnit tu = getTranslationUnitViaEditor(marker); - try { - if (tu.getLanguage().getLinkageID() == ILinkage.C_LINKAGE_ID) - return false; - } catch (CoreException e) { - // ignore - } - return true; + return getTranslationUnitViaEditorOrWorkspace(marker).map(tu -> { + try { + return tu.getLanguage().getLinkageID() != ILinkage.C_LINKAGE_ID; + } catch (CoreException e) { + return true; + } + }).orElse(true); + } + + /** + * Receives a translation unit from a given marker. The TU is received from + * an editor (if opened), + * or by calling {@link #getTranslationUnitViaWorkspace(IMarker)}. + * + * @param marker + * A marker in a translation unit + * @return The translation unit + */ + protected Optional getTranslationUnitViaEditorOrWorkspace(IMarker marker) { + return Optional.ofNullable(getTranslationUnitViaWorkspace(marker)).map(toWorkingCopy); } @Override diff --git a/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF index 75d1c1c7d8c..3fe3c4d2342 100644 --- a/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF +++ b/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF @@ -11,7 +11,7 @@ Export-Package: org.eclipse.cdt.internal.corext;x-internal:=true, org.eclipse.cdt.internal.corext.fix;x-internal:=true, org.eclipse.cdt.internal.corext.refactoring.code.flow;x-internal:=true, org.eclipse.cdt.internal.corext.template.c;x-internal:=true, - org.eclipse.cdt.internal.corext.util;x-friends:="org.eclipse.cdt.codan.ui", + org.eclipse.cdt.internal.corext.util;x-friends:="org.eclipse.cdt.codan.ui,org.eclipse.cdt.codan.checkers.ui", org.eclipse.cdt.internal.ui;x-friends:="org.eclipse.cdt.debug.edc.tests", org.eclipse.cdt.internal.ui.actions;x-internal:=true, org.eclipse.cdt.internal.ui.browser.opentype;x-internal:=true, diff --git a/pom.xml b/pom.xml index cc0f5b59104..29afaeedf72 100644 --- a/pom.xml +++ b/pom.xml @@ -175,6 +175,7 @@ core/org.eclipse.cdt.core.tests core/org.eclipse.cdt.ui.tests codan/org.eclipse.cdt.codan.core.test + codan/org.eclipse.cdt.codan.checkers.ui.test build/org.eclipse.cdt.managedbuilder.core.tests build/org.eclipse.cdt.managedbuilder.ui.tests build/org.eclipse.cdt.make.core.tests