use of org.eclipse.n4js.workspace.utils.N4JSPackageName in project n4js by eclipse.
the class ProjectImportEnablingScope method computeImportType.
/**
* Convenience method over
* {@link ImportSpecifierUtil#computeImportType(QualifiedName, boolean, N4JSProjectConfigSnapshot)}
*/
private ModuleSpecifierForm computeImportType(QualifiedName name, N4JSProjectConfigSnapshot project) {
final String firstSegment = name.getFirstSegment();
final N4JSProjectConfigSnapshot targetProject = findProject(new N4JSPackageName(firstSegment), project, true);
final boolean firstSegmentIsProjectName = targetProject != null;
return ImportSpecifierUtil.computeImportType(name, firstSegmentIsProjectName, targetProject);
}
use of org.eclipse.n4js.workspace.utils.N4JSPackageName in project n4js by eclipse.
the class ProjectImportEnablingScope method handleCollisions.
/**
* Special case handling when we have a definition and a pure JS file in the scope. In such cases we return with the
* description that corresponds to the definition file. Given several modules with the same name, there exists a
* resolution only iff:
* <ul>
* <li/>There is a plain js module, and
* <li/>An N4JSD module must be the corresponding definition module inside the corresponding definition project, and
* <li/>An d.ts module must be the corresponding definition module inside the corresponding definition project
* </ul>
* In case both an N4JSD and a d.ts module exist, the n4jsd module is returned. Otherwise either the N4JSD or the
* d.ts module is returned.
*/
private IEObjectDescription handleCollisions(List<IEObjectDescription> result, Map<IEObjectDescription, N4JSProjectConfigSnapshot> descriptionsToProject) {
Set<String> considerExtensions = ImmutableSet.<String>builder().addAll(ALL_JS_FILE_EXTENSIONS).add(N4JSD_FILE_EXTENSION).add(DTS_FILE_EXTENSION).build();
Map<String, IEObjectDescription> descr4Ext = new HashMap<>();
Map<String, N4JSProjectConfigSnapshot> prj4Ext = new HashMap<>();
for (IEObjectDescription res : result) {
String ext = URIUtils.fileExtension(res.getEObjectURI());
if (!considerExtensions.contains(ext)) {
continue;
}
N4JSProjectConfigSnapshot prj = descriptionsToProject.get(res);
if (descr4Ext.containsKey(ext)) {
// return null due to conflict
return null;
}
if (ext != null && prj != null) {
descr4Ext.put(ext, res);
prj4Ext.put(ext, prj);
}
}
if (descr4Ext.size() < 2) {
// return null due to missing project information
return null;
}
// NOTE: the priority between .js/.cjs/.mjs we implement in the following loop based on the order in constant
// ALL_JS_FILE_EXTENSIONS does not have an effect in practice, because conflicts between .js/.cjs/.mjs files are
// resolved up front (see #removeSuperfluousPlainJsFiles() and its invocation in #getSingleElement()), meaning
// we will always have only one of .js/.cjs/.mjs when reaching this point in the code:
N4JSProjectConfigSnapshot jsProject = null;
for (String jsFileExt : ALL_JS_FILE_EXTENSIONS) {
N4JSProjectConfigSnapshot removed = prj4Ext.remove(jsFileExt);
if (removed != null) {
jsProject = removed;
}
}
if (jsProject == null) {
// return null due to missing implementation module
return null;
}
Iterator<Entry<String, N4JSProjectConfigSnapshot>> iter = prj4Ext.entrySet().iterator();
while (iter.hasNext()) {
Entry<String, N4JSProjectConfigSnapshot> entry = iter.next();
String ext = entry.getKey();
N4JSProjectConfigSnapshot prj = entry.getValue();
if (!Objects.equals(jsProject.getPathAsFileURI(), prj.getPathAsFileURI())) {
// case both modules are in different projects: check here iff related
switch(ext) {
case N4JSD_FILE_EXTENSION:
if (prj.getType() != ProjectType.DEFINITION || !Objects.equals(prj.getDefinesPackage(), new N4JSPackageName(jsProject.getName()))) {
// return null due to conflict
return null;
}
break;
case DTS_FILE_EXTENSION:
if (prj.getType() != ProjectType.PLAINJS || !prj.getName().endsWith("/" + jsProject.getPackageName())) {
// return null due to conflict
return null;
}
break;
default:
}
} else {
// case both modules are in same project: assume one being the definition of the other
}
}
if (prj4Ext.size() == 1) {
String dExt = prj4Ext.keySet().iterator().next();
return descr4Ext.get(dExt);
} else if (prj4Ext.size() == 2) {
if (descr4Ext.containsKey(N4JSD_FILE_EXTENSION)) {
// paranoia check - should always be true
return descr4Ext.get(N4JSD_FILE_EXTENSION);
}
if (descr4Ext.containsKey(DTS_FILE_EXTENSION)) {
// paranoia check - should always be true
return descr4Ext.get(DTS_FILE_EXTENSION);
}
}
return null;
}
use of org.eclipse.n4js.workspace.utils.N4JSPackageName in project n4js by eclipse.
the class ProjectCompareHelper method compareModules.
/**
* Get the comparison for a module in a specific implementation specified by it's ID.
*
* @param module
* can be either Implementation or API
* @param implementationID
* the current implementation to compare with
*
* @param includePolyfills
* {@code true} if polyfills should be considered as the part of the API and the implementation.
* Otherwise {@code false}.
* @return a comparison between API and implementation with implementationID, or <code>null</code> if no project
* could be found, the module is not part of an API/IMPL ...
*/
public ProjectComparisonEntry compareModules(TModule module, N4JSPackageName implementationID, final boolean includePolyfills) {
Resource resource = module.eResource();
N4JSWorkspaceConfigSnapshot wc = workspaceAccess.getWorkspaceConfig(resource);
N4JSProjectConfigSnapshot project = workspaceAccess.findProjectContaining(resource);
if (project == null) {
return null;
}
N4JSProjectConfigSnapshot implProject = null;
N4JSProjectConfigSnapshot apiProject = null;
TModule apiModule = null;
TModule apiImplModule = null;
if (project.getImplementationId() == null) {
// this is NOT an implementation project, so assume we have the api
// need to load the correct implementation. Since there might be multiple implementors
ApiImplMapping mapping = ApiImplMapping.of(wc);
implProject = mapping.getImpl(project.getN4JSPackageName(), implementationID);
if (implProject == null) {
// no implementation found.
return null;
}
apiProject = project;
apiModule = module;
URI impUri = artifactHelper.findArtifact(implProject, apiModule.getQualifiedName(), Optional.of(N4JSGlobals.N4JS_FILE_EXTENSION));
if (impUri != null) {
IResourceDescriptions xtextIndex = workspaceAccess.getXtextIndex(module).orNull();
IResourceDescription resourceDescription = xtextIndex != null ? xtextIndex.getResourceDescription(impUri) : null;
if (resourceDescription != null) {
apiImplModule = workspaceAccess.loadModuleFromIndex(module.eResource().getResourceSet(), resourceDescription, false);
} else {
if (logger.isDebugEnabled()) {
logger.debug("...ouch nothing in index for " + impUri);
}
Resource implResource = module.eResource().getResourceSet().getResource(impUri, true);
apiImplModule = (TModule) implResource.getContents().get(1);
// .get(1);
if (logger.isDebugEnabled()) {
logger.debug("TModule loaded from Resource: " + apiImplModule);
}
}
} else {
// No implementation present.
if (logger.isDebugEnabled()) {
logger.debug("No implementation given. For " + apiModule.getQualifiedName());
}
}
} else {
// check that the implementation ID matches.
if (implementationID.equals(new N4JSPackageName(project.getImplementationId()))) {
implProject = project;
apiImplModule = module;
List<N4JSProjectConfigSnapshot> apiProjects = new ArrayList<>();
for (ProjectReference apiProjectRef : implProject.getProjectDescription().getImplementedProjects()) {
N4JSProjectConfigSnapshot currApiProject = wc.findProjectByID(apiProjectRef.getPackageName());
if (currApiProject != null) {
apiProjects.add(currApiProject);
}
}
labelA: for (N4JSProjectConfigSnapshot ap : apiProjects) {
URI apiURI = artifactHelper.findArtifact(ap, apiImplModule.getQualifiedName(), Optional.of(N4JSGlobals.N4JSD_FILE_EXTENSION));
if (apiURI != null) {
IResourceDescriptions xtextIndex = workspaceAccess.getXtextIndex(apiImplModule).orNull();
IResourceDescription resourceDescription = xtextIndex.getResourceDescription(apiURI);
if (resourceDescription != null) {
apiModule = workspaceAccess.loadModuleFromIndex(apiImplModule.eResource().getResourceSet(), resourceDescription, false);
if (apiModule != null)
break labelA;
}
}
}
} else {
return null;
}
}
if (apiModule != null) {
return compareModules(apiProject, apiModule, implProject, apiImplModule, includePolyfills);
} else {
// no apiModule --> this is not an implementation of API.
return null;
}
}
use of org.eclipse.n4js.workspace.utils.N4JSPackageName in project n4js by eclipse.
the class ProjectCompareHelper method getImplementationID.
/**
* Retrieves the implementation ID for an implementor of some API
*
* @param apiImplModule
* the implementor
* @return implementation ID if applicable - unset if the parameter is not implementing an API or is itself from an
* API definition.
*/
public Optional<N4JSPackageName> getImplementationID(TModule apiImplModule) {
N4JSProjectConfigSnapshot implProject = workspaceAccess.findProjectContaining(apiImplModule);
String implId = implProject != null ? implProject.getImplementationId() : null;
return implId != null ? Optional.of(new N4JSPackageName(implId)) : Optional.absent();
}
use of org.eclipse.n4js.workspace.utils.N4JSPackageName in project n4js by eclipse.
the class ProjectCompareHelper method createComparison.
/**
* First step in comparing API and implementation projects. This method will collect all API projects, the types
* declared there and their members and relate them to the corresponding types and members in all available
* implementation projects.
* <p>
* The second step of comparison is to compare an individual type/member to a corresponding type/member of a
* particular implementation via method {@link #compareApiImpl(ProjectComparisonEntry, int)}.
* <p>
* Usually, this second step is performed lazily when method <code>#compareApiImpl()</code> is invoked; however, by
* setting <code>fullCompare</code> to <code>true</code>, this is performed up-front here causing all results to be
* stored in a cache in the entries, and then subsequent calls to <code>#compareApiImpl()</code> will just read from
* that cache.
* <p>
* Returns <code>null</code> in case of error and adds human-readable error messages to the given list.
*/
public ProjectComparison createComparison(boolean fullCompare, List<String> addErrorMessagesHere) {
final ResourceSet resourceSet = workspaceAccess.createResourceSet();
final N4JSWorkspaceConfigSnapshot wc = workspaceAccess.getWorkspaceConfig(resourceSet);
final IResourceDescriptions index = workspaceAccess.getXtextIndex(resourceSet).orNull();
if (index == null) {
addErrorMessagesHere.add("failed to create a new resource set with properly configured workspace configuration and index");
return null;
}
final ApiImplMapping mapping = ApiImplMapping.of(wc);
if (mapping.hasErrors()) {
if (addErrorMessagesHere != null)
addErrorMessagesHere.addAll(mapping.getErrorMessages());
return null;
}
final List<N4JSPackageName> allImplIds = mapping.getAllImplIds();
final int implCount = allImplIds.size();
final ProjectComparison root = new ProjectComparison(allImplIds.toArray(new N4JSPackageName[implCount]));
for (N4JSPackageName currApiId : mapping.getApiIds()) {
final N4JSProjectConfigSnapshot currApi = mapping.getApi(currApiId);
final N4JSProjectConfigSnapshot[] currImpls = new N4JSProjectConfigSnapshot[implCount];
for (int idx = 0; idx < implCount; idx++) {
final N4JSPackageName currImplId = allImplIds.get(idx);
currImpls[idx] = mapping.getImpl(currApiId, currImplId);
}
createEntries(root, currApi, currImpls, resourceSet, index);
}
// compare all implementations in all entries and store in cache (if requested)
if (fullCompare) {
root.getAllEntries().forEach(currE -> {
for (int implIdx = 0; implIdx < implCount; implIdx++) compareApiImpl(currE, implIdx);
});
}
return root;
}
Aggregations