Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SONARPY-2303 Stop running V1 type inference during the indexing phase #2131

Merged
merged 4 commits into from
Dec 6, 2024

Conversation

guillaume-dequenne-sonarsource
Copy link
Contributor

@guillaume-dequenne-sonarsource guillaume-dequenne-sonarsource commented Nov 5, 2024

@guillaume-dequenne-sonarsource guillaume-dequenne-sonarsource changed the title SONARPY-2303 SONARPY-2303 Stop running V1 type inference during the indexing phase Nov 5, 2024
@guillaume-dequenne-sonarsource guillaume-dequenne-sonarsource force-pushed the SONARPY-2303 branch 2 times, most recently from 0be3f9a to 6e6e789 Compare November 5, 2024 14:39
@guillaume-dequenne-sonarsource guillaume-dequenne-sonarsource force-pushed the SONARPY-2303 branch 3 times, most recently from 4ca0b3f to 1759e47 Compare November 6, 2024 09:15
Base automatically changed from MMF-3945 to master November 6, 2024 16:31
Copy link

sonarqube-next bot commented Nov 6, 2024

Quality Gate failed Quality Gate failed

Failed conditions
17 New issues
85.6% Coverage on New Code (required ≥ 95%)

See analysis details on SonarQube

Catch issues before they fail your Quality Gate with our IDE extension SonarLint SonarLint

@guillaume-dequenne-sonarsource guillaume-dequenne-sonarsource force-pushed the SONARPY-2303 branch 17 times, most recently from 24cf2b8 to 344bd13 Compare December 4, 2024 15:02
@@ -59,7 +64,7 @@ public CacheContext cacheContext() {

@Beta
public Collection<Symbol> stubFilesSymbols() {
return TypeShed.stubFilesSymbols();
return projectLevelSymbolTable.typeShedDescriptorsProvider().stubFilesSymbols(projectLevelSymbolTable);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: I notice it's a bit weird to pass the projectLevelSymbolTable to the typeShedDescriptorsProvider when it is itself a part of the projectLevelSymbolTable. However, given it is code meant to disappear after we finish the removal of the V1 engine, I think it's okay to keep as it is.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not delegate this method inside the ProjectLevelSymbolTable to hide it behind the scenes?

@guillaume-dequenne-sonarsource guillaume-dequenne-sonarsource marked this pull request as ready for review December 6, 2024 08:51
* Returns stub symbols to be used by SonarSecurity.
* Ambiguous symbols that only contain class symbols are disambiguated with latest Python version.
*/
public Collection<Symbol> stubFilesSymbols(ProjectLevelSymbolTable projectLevelSymbolTable) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that the Descriptors provider should not operate with the Symbol model, it should just provide descriptors. The conversion from the descriptor to the symbol model is on the projectLevelSymbolTable side

default:
throw new IllegalStateException(String.format("Error while creating a Symbol from a Descriptor: Unexpected descriptor kind: %s", descriptor.kind()));
}
}

private static Descriptor recreateDescriptorFromAlias(AliasDescriptor aliasDescriptor) {
return switch (aliasDescriptor.originalDescriptor().kind()) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if replace this kind switch-case with just instanceof if-else - it will allow to get rid of unsafe class casts in the recreateFunctionDescriptor and the recreateClassDescriptor methods like:

private static Descriptor recreateDescriptorFromAlias(AliasDescriptor aliasDescriptor) {
  if (aliasDescriptor.originalDescriptor() instanceof FunctionDescriptor functionDescriptor) {
    return recreateFunctionDescriptor(aliasDescriptor, functionDescriptor);
  } else if (aliasDescriptor.originalDescriptor() instanceof ClassDescriptor classDescriptor) {
    return recreateClassDescriptor(aliasDescriptor, classDescriptor);
  }
  throw new IllegalStateException(String.format("Error while recreating a descriptor from an alias: Unexpected alias kind: %s", aliasDescriptor.kind()));
}

Copy link
Contributor

@thomas-serre-sonarsource thomas-serre-sonarsource left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Great job!!
Thanks for rewriting the git history; it was appreciated for the review.

I left mainly questions but no show-stopper.
I put it back in progress for you to answer them.

var typesBySymbol = typeInferenceV2.inferTypes(fileInput);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

importsByModule.put(fullyQualifiedModuleName, typeInferenceV2.importedModulesFQN());

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change

Comment on lines 147 to 166
public Collection<Symbol> stubFilesSymbols(ProjectLevelSymbolTable projectLevelSymbolTable) {
if (cachedSymbols != null) {
return cachedSymbols;
}
Collection<Descriptor> allDescriptors = new ArrayList<>(stubFilesDescriptors());
allDescriptors.addAll(builtinDescriptors().values());
record Pair(Symbol symbol, Descriptor descriptor){}

Map<String, Pair> symbolsByFqn = new HashMap<>();
cachedSymbols = new HashSet<>();

for (Descriptor descriptor : allDescriptors) {
if (descriptor.fullyQualifiedName() != null) {
Pair pair = symbolsByFqn.computeIfAbsent(descriptor.fullyQualifiedName(), k ->
new Pair(DescriptorUtils.symbolFromDescriptor(descriptor, projectLevelSymbolTable, null, new HashMap<>(), new HashMap<>()), descriptor));
cachedSymbols.add(pair.symbol());
}
}
return cachedSymbols;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you have to introduce a record here?

Suggested change
public Collection<Symbol> stubFilesSymbols(ProjectLevelSymbolTable projectLevelSymbolTable) {
if (cachedSymbols != null) {
return cachedSymbols;
}
Collection<Descriptor> allDescriptors = new ArrayList<>(stubFilesDescriptors());
allDescriptors.addAll(builtinDescriptors().values());
record Pair(Symbol symbol, Descriptor descriptor){}
Map<String, Pair> symbolsByFqn = new HashMap<>();
cachedSymbols = new HashSet<>();
for (Descriptor descriptor : allDescriptors) {
if (descriptor.fullyQualifiedName() != null) {
Pair pair = symbolsByFqn.computeIfAbsent(descriptor.fullyQualifiedName(), k ->
new Pair(DescriptorUtils.symbolFromDescriptor(descriptor, projectLevelSymbolTable, null, new HashMap<>(), new HashMap<>()), descriptor));
cachedSymbols.add(pair.symbol());
}
}
return cachedSymbols;
}
public Collection<Symbol> stubFilesSymbols(ProjectLevelSymbolTable projectLevelSymbolTable) {
if (cachedSymbols != null) {
return cachedSymbols;
}
Collection<Descriptor> allDescriptors = new ArrayList<>(stubFilesDescriptors());
allDescriptors.addAll(builtinDescriptors().values());
Map<String, Symbol> symbolsByFqn = new HashMap<>();
cachedSymbols = new HashSet<>();
for (Descriptor descriptor : allDescriptors) {
if (descriptor.fullyQualifiedName() != null) {
Symbol symbol = symbolsByFqn.computeIfAbsent(descriptor.fullyQualifiedName(), k -> DescriptorUtils.symbolFromDescriptor(descriptor, projectLevelSymbolTable, null, new HashMap<>(), new HashMap<>()));
cachedSymbols.add(symbol);
}
}
return cachedSymbols;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really remember why I needed that in a previous iteration...but certainly I don't anymore, good catch!

default:
throw new IllegalStateException(String.format("Error while creating a Symbol from a Descriptor: Unexpected descriptor kind: %s", descriptor.kind()));
}
}

private static Descriptor recreateDescriptorFromAlias(AliasDescriptor aliasDescriptor) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there are no unit tests for this function, especially in the case that the original descriptor is not a class or a function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And actually there was a bug in the logger, as I was logging the type of the AliasDescriptor instead of the original descriptor, good catch!

Copy link
Contributor

@thomas-serre-sonarsource thomas-serre-sonarsource left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! Well done 💪 🚀

@guillaume-dequenne-sonarsource guillaume-dequenne-sonarsource merged commit 74cb3f2 into master Dec 6, 2024
9 of 10 checks passed
@guillaume-dequenne-sonarsource guillaume-dequenne-sonarsource deleted the SONARPY-2303 branch December 6, 2024 15:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants