diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/BuildErrorReporter.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/BuildErrorReporter.java index a01e25f963..1c196749a7 100644 --- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/BuildErrorReporter.java +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/BuildErrorReporter.java @@ -19,8 +19,9 @@ package org.eclipse.pde.internal.core.builders; import java.io.File; -import java.io.FilenameFilter; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -28,8 +29,7 @@ import java.util.Map; import java.util.Objects; import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; +import java.util.function.Predicate; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.ParserConfigurationException; @@ -151,22 +151,6 @@ public void addAttributes(Map attributes) { } } - static class WildcardFilenameFilter implements FilenameFilter { - - private final Pattern pattern; - - public WildcardFilenameFilter(String file) { - pattern = PatternConstructor.createPattern(file, false); - } - - @Override - public boolean accept(File dir, String name) { - Matcher matcher = pattern.matcher(name); - return matcher.matches(); - } - - } - protected List fProblemList = new ArrayList<>(); protected int fBuildSeverity; protected int fClasspathSeverity; @@ -736,12 +720,15 @@ private void validateBinIncludes(IBuildEntry binIncludes, String key) { // check for wildcards IPath project = fFile.getProject().getLocation(); if (project != null && token != null) { - File projectFile = project.toFile(); - File[] files = projectFile.listFiles(new WildcardFilenameFilter(token)); - for (File file : files) { - if (file.toString().endsWith(key)) { - return true; + Predicate isMatch = toMatcher(token); + try (var files = Files.newDirectoryStream(project.toPath(), + path -> isMatch.test(path.getFileName().toString()));) { + for (Path file : files) { + if (file.toString().endsWith(key)) { + return true; + } } + } catch (IOException e) { // ignore } } return false; @@ -820,29 +807,14 @@ private void validateMissingSourceInBinIncludes(IBuildEntry binIncludes, List> matchers = Arrays.stream(binIncludes.getTokens()).map(BuildErrorReporter::toMatcher) + .toList(); + boolean found = matchers.stream().anyMatch(m -> m.test(libName)); // account for trailing slash on class file folders - if (!found) { - IPath path = IPath.fromOSString(key); - if (path.getFileExtension() == null) { - if (!key.endsWith("/")) { //$NON-NLS-1$ - key = key + "/"; //$NON-NLS-1$ - for (String token : binIncludesTokens) { - Pattern pattern = PatternConstructor.createPattern(token, false); - if (pattern.matcher(key).matches()) { - found = true; - } - } - } - } + if (!found && IPath.fromOSString(libName).getFileExtension() == null && !libName.endsWith("/")) { //$NON-NLS-1$ + String folderName = libName + "/"; //$NON-NLS-1$ + found = matchers.stream().anyMatch(m -> m.test(folderName)); } if (!found) { String msg = NLS.bind(PDECoreMessages.BuildErrorReporter_binIncludesMissing, key); @@ -1333,6 +1305,10 @@ private VirtualMarker report(String message, int line, int problemID, String bui return marker; } + private static Predicate toMatcher(String token) { + return PatternConstructor.createPattern(token, false).asMatchPredicate(); + } + public boolean isCustomBuild() { WorkspaceBuildModel wbm = new WorkspaceBuildModel(fFile); IBuild build = wbm.getBuild(); diff --git a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/SourceEntryErrorReporter.java b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/SourceEntryErrorReporter.java index d796051dec..ae530c0679 100644 --- a/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/SourceEntryErrorReporter.java +++ b/ui/org.eclipse.pde.core/src/org/eclipse/pde/internal/core/builders/SourceEntryErrorReporter.java @@ -16,7 +16,7 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -26,7 +26,6 @@ import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IResource; -import org.eclipse.core.resources.IResourceVisitor; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.jdt.core.IClasspathEntry; @@ -169,127 +168,24 @@ public List getSourceFolders() { * Represents a default or custom encoding property for a resource * within a library. */ - static class EncodingEntry { - - private final String fEncoding; - private final IResource fResource; - - /** - * Constructs an encoding entry for the given resource. - * - * @param resource resource - * @param encoding the encoding identifier - */ - EncodingEntry(IResource resource, String encoding) { - fEncoding = encoding; - fResource = resource; - } - - /** - * Returns the explicit encoding for this entry. - * - * @return explicit encoding - */ - public String getEncoding() { - return fEncoding; - } - - /** - * Returns the resource this encoding is associated with. - * - * @return associated resource - */ - public IResource getResource() { - return fResource; - } - - @Override - public String toString() { - return getValue(); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof EncodingEntry other) { - return other.fEncoding.equals(fEncoding) && other.fResource.equals(fResource); - } - return false; - } - - @Override - public int hashCode() { - return fEncoding.hashCode() + fResource.hashCode(); - } + private record EncodingEntry(IResource resource, String encoding) { /** * Returns the generated value of this entry for the build.properties file. * * @return value to enter into build.properties */ - String getValue() { - StringBuilder buf = new StringBuilder(); - IContainer root = PDEProject.getBundleRoot(fResource.getProject()); - buf.append(fResource.getFullPath().makeRelativeTo(root.getFullPath()).makeAbsolute()); - buf.append('['); - buf.append(fEncoding); - buf.append(']'); - return buf.toString(); - } - - } - - /** - * Visits a source folder gathering encodings. - */ - class Visitor implements IResourceVisitor { - - String[] fLibs = null; - - Visitor(SourceFolder folder) { - List list = folder.getLibs(); - fLibs = list.toArray(new String[list.size()]); - } - @Override - public boolean visit(IResource resource) throws CoreException { - String encoding = null; - switch (resource.getType()) { - case IResource.FOLDER : - encoding = ((IFolder) resource).getDefaultCharset(false); - break; - case IResource.FILE : - IFile file = (IFile) resource; - // only worry about .java files - if (file.getFileExtension() != null && file.getFileExtension().equals("java")) { //$NON-NLS-1$ - encoding = file.getCharset(false); - } - break; - } - if (encoding != null) { - EncodingEntry entry = new EncodingEntry(resource, encoding); - for (String lib : fLibs) { - List encodings = fCustomEncodings.get(lib); - if (encodings == null) { - encodings = new ArrayList<>(); - fCustomEncodings.put(lib, encodings); - } - encodings.add(entry); - } - } - return true; + public String toString() { + IContainer root = PDEProject.getBundleRoot(resource().getProject()); + return resource.getFullPath().makeRelativeTo(root.getFullPath()).makeAbsolute() + "[" + encoding + "]"; //$NON-NLS-1$ //$NON-NLS-2$ } - } private final Map fSourceFolderMap = new HashMap<>(4); private final Map fOutputFolderMap = new HashMap<>(4); private IBuild fBuild = null; - /** - * Maps library name to custom {@link EncodingEntry}'s for this library. - */ - Map> fCustomEncodings = new HashMap<>(); - public void initialize(List sourceEntries, List outputEntries, IClasspathEntry[] cpes) { IPath defaultOutputLocation = null; IJavaProject javaProject = JavaCore.create(fProject); @@ -485,43 +381,7 @@ private void validateOutputEntries() { private List validateSourceEntries() { - class MissingOutputEntry { - private final List fSrcFolders = new ArrayList<>(1); - private final List fOutputFolders = new ArrayList<>(1); - - public String getOutputList() { - return generateList(fOutputFolders); - } - - public String getSourceList() { - return generateList(fSrcFolders); - } - - private String generateList(List strings) { - StringBuilder buffer = new StringBuilder(); - Iterator iterator = strings.iterator(); - while (iterator.hasNext()) { - String next = iterator.next(); - buffer.append(next); - if (iterator.hasNext()) { - buffer.append(','); - buffer.append(' '); - } - } - return buffer.toString(); - } - - public void addSrcFolder(String sourcePath) { - if (!fSrcFolders.contains(sourcePath)) { - fSrcFolders.add(sourcePath); - } - } - - public void addOutputFolder(String outputPath) { - if (!fOutputFolders.contains(outputPath)) { - fOutputFolders.add(outputPath); - } - } + record MissingOutputEntry(Set fSrcFolders, Set fOutputFolders) { } Map missingOutputEntryErrors = new HashMap<>(4); @@ -549,9 +409,9 @@ public void addOutputFolder(String outputPath) { String libName = sourceFolder.getLibs().get(0); MissingOutputEntry errorEntry = missingOutputEntryErrors.computeIfAbsent(libName, - n -> new MissingOutputEntry()); - errorEntry.addSrcFolder(sourcePath.toString()); - errorEntry.addOutputFolder(outputFolder.getToken()); + n -> new MissingOutputEntry(new LinkedHashSet<>(1), new LinkedHashSet<>(1))); + errorEntry.fSrcFolders().add(sourcePath.toString()); + errorEntry.fOutputFolders().add(outputFolder.getToken()); } if (sourceFolder.getDupeLibName() != null) { @@ -564,8 +424,10 @@ public void addOutputFolder(String outputPath) { }); missingOutputEntryErrors.forEach((libName, errorEntry) -> { - String message = NLS.bind(PDECoreMessages.SourceEntryErrorReporter_MissingOutputEntry, errorEntry.getSourceList(), PROPERTY_OUTPUT_PREFIX + libName); - prepareError(PROPERTY_OUTPUT_PREFIX + libName, errorEntry.getOutputList(), message, PDEMarkerFactory.B_ADDITION, fMissingOutputLibSeverity,CompilerFlags.P_BUILD_MISSING_OUTPUT, PDEMarkerFactory.CAT_OTHER); + String sourceList = String.join(", ", errorEntry.fSrcFolders()); //$NON-NLS-1$ + String outputList = String.join(", ", errorEntry.fOutputFolders()); //$NON-NLS-1$ + String message = NLS.bind(PDECoreMessages.SourceEntryErrorReporter_MissingOutputEntry, sourceList, PROPERTY_OUTPUT_PREFIX + libName); + prepareError(PROPERTY_OUTPUT_PREFIX + libName, outputList, message, PDEMarkerFactory.B_ADDITION, fMissingOutputLibSeverity,CompilerFlags.P_BUILD_MISSING_OUTPUT, PDEMarkerFactory.CAT_OTHER); }); return toValidate; } @@ -578,6 +440,9 @@ private void validateSourceEncodings(List toValidate) { // Maps library name to default encoding for that library (or not // present if there is no explicit default encoding specified). Map defaultLibraryEncodings = new HashMap<>(); + // Maps library name to custom EncodingEntry 's for this library. + Map> customEncodings = new HashMap<>(); + // build map of expected encodings for (SourceFolder sourceFolder : toValidate) { IPath sourcePath = sourceFolder.getPath(); @@ -592,7 +457,24 @@ private void validateSourceEncodings(List toValidate) { defaultLibraryEncodings.put(lib, encoding); } } - container.accept(new Visitor(sourceFolder)); + container.accept(resource -> { + String resourceEncoding = switch (resource.getType()) { + case IResource.FOLDER -> ((IFolder) resource).getDefaultCharset(false); + case IResource.FILE -> { + IFile file = (IFile) resource; + // only worry about .java files + yield "java".equals(file.getFileExtension()) ? file.getCharset(false) : null; //$NON-NLS-1$ + } + default -> null; + }; + if (resourceEncoding != null) { + EncodingEntry entry = new EncodingEntry(resource, resourceEncoding); + for (String lib : sourceFolder.getLibs()) { + customEncodings.computeIfAbsent(lib, l -> new ArrayList<>()).add(entry); + } + } + return true; + }); } catch (CoreException e) { // Can't validate if unable to retrieve encoding PDECore.log(e); @@ -654,24 +536,24 @@ private void validateSourceEncodings(List toValidate) { } } // compare with workspace encodings - List workspace = fCustomEncodings.remove(lib); + List workspace = customEncodings.remove(lib); if (workspace == null) { String msg = NLS.bind(PDECoreMessages.SourceEntryErrorReporter_5, lib); prepareEncodingError(name, null, msg, PDEMarkerFactory.B_REMOVAL); } else { Map map = new HashMap<>(); for (EncodingEntry ee : workspace) { - map.put(ee.getResource(), ee.getEncoding()); + map.put(ee.resource(), ee.encoding()); } for (EncodingEntry ee : encodings) { - String specified = ee.getEncoding(); - String expected = map.remove(ee.getResource()); + String specified = ee.encoding(); + String expected = map.remove(ee.resource()); if (expected == null) { - String msg = NLS.bind(PDECoreMessages.SourceEntryErrorReporter_6, expected, ee.getResource().getProjectRelativePath()); + String msg = NLS.bind(PDECoreMessages.SourceEntryErrorReporter_6, expected, ee.resource().getProjectRelativePath()); prepareEncodingError(name, ee.toString(), msg, PDEMarkerFactory.B_REMOVAL); } else { if (!specified.equals(expected)) { - String msg = NLS.bind(PDECoreMessages.SourceEntryErrorReporter_7, new String[] { expected, ee.getResource().getProjectRelativePath().toString(), specified }); + String msg = NLS.bind(PDECoreMessages.SourceEntryErrorReporter_7, new String[] { expected, ee.resource().getProjectRelativePath().toString(), specified }); prepareEncodingError(name, ee.toString(), msg, PDEMarkerFactory.M_ONLY_CONFIG_SEV); } } @@ -697,9 +579,9 @@ private void validateSourceEncodings(List toValidate) { }); // check for unspecified custom encodings - fCustomEncodings.forEach((lib, encodings) -> { + customEncodings.forEach((lib, encodings) -> { for (EncodingEntry encoding : encodings) { - String msg = NLS.bind(PDECoreMessages.SourceEntryErrorReporter_8, encoding.getEncoding(), encoding.getResource().getProjectRelativePath()); + String msg = NLS.bind(PDECoreMessages.SourceEntryErrorReporter_8, encoding.encoding(), encoding.resource().getProjectRelativePath()); prepareEncodingError(PROPERTY_JAVAC_CUSTOM_ENCODINGS_PREFIX + lib, encoding.toString(), msg, PDEMarkerFactory.B_ADDITION); } });