Olá pessoal. Hoje temos outro projeto da Microsoft em teste. Pelo título do artigo, você pode supor que desta vez os desenvolvedores não puderam nos agradar com um grande número de erros. Esperamos que os autores do projeto não sejam ofendidos pelo nome. Afinal, um pequeno número de erros é excelente, não é? No entanto, algo interessante foi encontrado no código do Azure PowerShell. Sugerimos que você se familiarize com os recursos deste projeto e observe os erros encontrados no analisador PV # C PVS-Studio.
Sobre o projeto
O Azure PowerShell é um cmdlet que permite gerenciar recursos do
Azure diretamente da linha de comando do
PowerShell . O principal objetivo deste conjunto é simplificar o aprendizado e o início rápido do desenvolvimento do Azure. O Azure PowerShell fornece aos administradores e desenvolvedores recursos avançados para criar, implantar e gerenciar aplicativos do Microsoft Azure.
O Azure PowerShell é desenvolvido no ambiente .NET Standard e é suportado pelo PowerShell 5.1 para Windows e PowerShell 6.xe superior para todas as plataformas. O
código-fonte do Azure PowerShell está disponível no GitHub.
Recentemente, os projetos da Microsoft costumam me chamar a atenção. Na minha opinião, a qualidade desses projetos geralmente é a melhor. Embora, é claro, não sem exceções, como foi o artigo "
WinForms: erros, Holmes ". No entanto, desta vez tudo está normal. O projeto é grande: 6845 arquivos. Código-fonte .cs contêm cerca de 700 mil linhas, exceto vazias (testes, bem como avisos do terceiro nível de confiabilidade, não levei em consideração). Havia muito poucos erros para esse volume de código: não mais que cem. Existem muitas situações do mesmo tipo, portanto, para o artigo, selecionei os aspectos mais interessantes. Os erros, como normalmente faço, são classificados pelos números de diagnóstico do PVS-Studio.
Também deparei com fragmentos de código que parecem erros, mas não consegui concluir inequivocamente a existência de um problema real, pois não estou familiarizado o suficiente com os recursos de desenvolvimento do PowerShell. Espero que entre os leitores haja especialistas neste assunto e que me ajude. Sobre isso abaixo.
Antes do início da "análise", observo a peculiaridade do projeto em termos de sua estrutura. O código-fonte do Azure PowerShell consiste em mais de setenta soluções do Visual Studio. Algumas soluções incluem projetos de outras soluções. Tal estrutura atrasou um pouco a análise (não muito). O restante da verificação não causou dificuldades. Por conveniência, na linha da mensagem de erro (entre colchetes), indicarei o nome da solução na qual esse erro foi detectado.
Resultados da validação
V3001 Existem sub-expressões idênticas 'strTimespan.Contains ("M")' à esquerda e à direita da '||' operador. AzureServiceBusCmdletBase.cs 187 (EventGrid)
public static TimeSpan ParseTimespan(string strTimespan) { .... if (strTimespan.Contains("P") || strTimespan.Contains("D") || strTimespan.Contains("T") || strTimespan.Contains("H") || strTimespan.Contains("M") || strTimespan.Contains("M")) .... }
Um exemplo de erro bastante óbvio, que somente o desenvolvedor pode corrigir. Nesse caso, é completamente incompreensível se estamos lidando com a duplicação de código que não afeta nada ou, em vez de
"M", algo mais deve aparecer em uma das duas últimas verificações.
V3001 Existem
subexpressões idênticas 'this.AggregationType! = Null' à esquerda e à direita do operador '&&'. GetAzureRmMetricCommand.cs 156 (Monitor)
public AggregationType? AggregationType { get; set; } .... protected override void ProcessRecordInternal() { .... string aggregation = (this.AggregationType != null && this.AggregationType.HasValue) ? this.AggregationType.Value.ToString() : null; .... }
Provavelmente não há erro aqui. Este é um exemplo de código redundante. Às vezes, esse código pode indicar um nível insuficiente de conhecimento do desenvolvedor. O fato é que as verificações
this.AggregationType! = Null e
this.AggregationType.HasValue são idênticas. Basta usar um deles (qualquer um). Pessoalmente, prefiro a
opção HasValue :
string aggregation = this.AggregationType.HasValue ? this.AggregationType.Value.ToString() : null;
V3003 O uso do
padrão 'if (A) {...} else if (A) {...}' foi detectado. Há uma probabilidade de presença de erro lógico. Verifique as linhas: 152, 163. GetAzureRmRecoveryServicesBackupProtectionPolicy.cs 152 (RecoveryServices)
public override void ExecuteCmdlet() { .... if( WorkloadType == Models.WorkloadType.AzureVM ) { .... } .... else if( WorkloadType == Models.WorkloadType.AzureFiles ) { if( BackupManagementType != Models.BackupManagementType.AzureStorage ) { throw new ArgumentException( Resources.AzureFileUnsupportedBackupManagementTypeException ); } serviceClientProviderType = ServiceClientHelpers. GetServiceClientProviderType( Models.WorkloadType.AzureFiles ); } else if( WorkloadType == Models.WorkloadType.AzureFiles ) { if( BackupManagementType != Models.BackupManagementType.AzureStorage ) { throw new ArgumentException( Resources.AzureFileUnsupportedBackupManagementTypeException ); } serviceClientProviderType = ServiceClientHelpers. GetServiceClientProviderType( Models.WorkloadType.AzureFiles ); } .... }
Os
outros dois blocos
se são absolutamente idênticos, incluindo a condição e o corpo do bloco. Esses erros geralmente são cometidos ao usar o método copiar e colar no trabalho. A questão novamente é a criticidade desse erro. Se essa não é uma simples duplicação de código, podemos falar sobre a falta da verificação necessária e o conjunto de ações correspondente. O autor precisa editar o código.
V3005 A variável 'this.VM.OSProfile.WindowsConfiguration.ProvisionVMAgent' é atribuída a si mesma. SetAzureVMOperatingSystemCommand.cs 298 (Compute)
public override void ExecuteCmdlet() { ....
O valor da propriedade é atribuído a si próprio. Dê uma olhada no anúncio dele:
[JsonProperty(PropertyName = "provisionVMAgent")] public bool? ProvisionVMAgent { get; set; }
A descrição
JsonProperty diz "Instrui o Newtonsoft.Json.JsonSerializer para sempre serializar o membro com o nome especificado". Parece que tudo é simples e há um erro óbvio. Também é confuso o uso explícito
disso para acessar uma propriedade. Talvez, por engano, alguma outra variável não tenha sido especificada em vez
disso . Mas, por enquanto, não tiraremos conclusões. O fato é que, no código do Azure PowerShell, conheci muitas dessas atribuições (a propriedade é atribuída a si mesma). Aqui está outro exemplo de uma atribuição que é muito semelhante a um erro:
V3005 A variável 'this.LastHeartbeat' é atribuída a si mesma. PSFabricDetails.cs 804 (RecoveryServices)
public ASRInMageAzureV2SpecificRPIDetails( InMageAzureV2ReplicationDetails details) { this.LastHeartbeat = this.LastHeartbeat;
Preste atenção na segunda e nas seguintes tarefas. No lado direito da expressão, não é
isso que aparece, mas
detalhes .
Dê uma olhada na declaração
desta propriedade.LastHeartbeat:
public DateTime? LastHeartbeat { get; set; }
Por fim, procure uma propriedade com o mesmo nome na classe
InMageAzureV2ReplicationDetails . Essa propriedade é declarada lá:
public class InMageAzureV2ReplicationDetails : ReplicationProviderSpecificSettings { .... [JsonProperty(PropertyName = "lastHeartbeat")] public DateTime? LastHeartbeat { get; set; } .... }
Bem, neste caso, estou pronto para admitir que esse gatilho é um erro real. Mas o que fazer com os seguintes gatilhos? Neles, diferentemente dos dois fragmentos de código anteriores, há uma atribuição múltipla de propriedades para si mesmos. Isso já é menos como um erro:
- V3005 A variável 'this.ResourceGroupName' é atribuída a si mesma. RemoveAzureRmExpressRouteConnectionCommand.cs 84 (CognitiveServices)
- V3005 A variável 'this.ExpressRouteGatewayName' é atribuída a si mesma. RemoveAzureRmExpressRouteConnectionCommand.cs 85 (CognitiveServices)
- V3005 A variável 'this.Name' é atribuída a si mesma. RemoveAzureRmExpressRouteConnectionCommand.cs 86 (CognitiveServices)
[Cmdlet(VerbsCommon.Remove, ResourceManager.Common.AzureRMConstants.AzureRMPrefix + "ExpressRouteConnection", DefaultParameterSetName = CortexParameterSetNames.ByExpressRouteConnectionName, SupportsShouldProcess = true), OutputType(typeof(bool))] public class RemoveExpressRouteConnectionCommand : ExpressRouteConnectionBaseCmdlet { [Parameter( Mandatory = true, ParameterSetName = CortexParameterSetNames.ByExpressRouteConnectionName, HelpMessage = "The resource group name.")] [ResourceGroupCompleter] [ValidateNotNullOrEmpty] public string ResourceGroupName { get; set; } .... public override void Execute() { if (....) { this.ResourceGroupName = this.ResourceGroupName; this.ExpressRouteGatewayName = this.ExpressRouteGatewayName; this.Name = this.Name; } .... } .... }
O método
Execute contém três atribuições consecutivas de propriedades para elas mesmas. Por precaução, dei uma declaração completa da classe
RemoveExpressRouteConnectionCommand com todos os seus atributos, bem como uma declaração da propriedade
ResourceGroupName (as outras duas propriedades são declaradas da mesma maneira). Foi tão desencadeador que me fez pensar sobre a pergunta: "Isso é um erro?" Suspeito que algum tipo de mágica interna do desenvolvimento do PowerShell possa acontecer aqui. Espero que entre os leitores haja especialistas com conhecimento sobre esse assunto. Não estou pronto para concluir neste caso.
V3006 O objeto foi criado, mas não está sendo usado. A palavra-chave 'throw' pode estar ausente: throw new ArgumentException (FOO). StartAzureRmRecoveryServicesAsrTestFailoverJob.cs 259 (RecoveryServices)
private void StartRPITestFailover() { .... if (....) { .... } else { new ArgumentException( Resources .UnsupportedDirectionForTFO);
Ignorou a palavra-chave
throw . Além disso, o comentário diz que a exceção deve ser lançada. Na solução
RecoveryServices , encontrei vários erros semelhantes:
- V3006 O objeto foi criado, mas não está sendo usado. A palavra-chave 'throw' pode estar ausente: throw new ArgumentException (FOO). StartAzureRmRecoveryServicesAsrTestFailoverJob.cs 305 (RecoveryServices)
- V3006 O objeto foi criado, mas não está sendo usado. A palavra-chave 'throw' pode estar ausente: throw new ArgumentException (FOO). StartAzureRmRecoveryServicesAsrUnPlannedFailover.cs 278 (RecoveryServices)
- V3006 O objeto foi criado, mas não está sendo usado. A palavra-chave 'throw' pode estar ausente: throw new ArgumentException (FOO). StartAzureRmRecoveryServicesAsrUnPlannedFailover.cs 322 (RecoveryServices)
- V3006 O objeto foi criado, mas não está sendo usado. A palavra-chave 'throw' pode estar ausente: throw new ArgumentException (FOO). UpdateAzureRmRecoveryServicesAsrProtectionDirection.cs 421 (RecoveryServices)
- V3006 O objeto foi criado, mas não está sendo usado. A palavra-chave 'throw' pode estar ausente: throw new ArgumentException (FOO). UpdateAzureRmRecoveryServicesAsrProtectionDirection.cs 452 (RecoveryServices)
A expressão
V3022 'apiType.HasValue' é sempre falsa. ApiManagementClient.cs 1134 (ApiManagement)
private string GetApiTypeForImport(...., PsApiManagementApiType? apiType) { .... if (apiType.HasValue) { switch(apiType.Value) { case PsApiManagementApiType.Http: return SoapApiType.SoapToRest; case PsApiManagementApiType.Soap: return SoapApiType.SoapPassThrough; default: return SoapApiType.SoapPassThrough; } } return apiType.HasValue ?
A lógica do trabalho é violada. Se
apiType contiver um valor, o controle não alcançará a expressão de
retorno no final do método (todas as ramificações do
comutador contêm
retorno ). Caso contrário, o método sempre retornará
PsApiManagementApiType.Http.ToString ("g") e
apiType.Value.ToString ("g") , respectivamente, nunca serão retornados.
A expressão
V3022 'automationJob! = Null && automationJob == null' é sempre falsa. NodeConfigurationDeployment.cs 199 (automação)
public NodeConfigurationDeployment( ...., Management.Automation.Models.Job automationJob = null, ....) { .... if (automationJob != null && automationJob == null) return; .... }
O código paradoxal. Dois cheques que se contradizem. Provavelmente, a segunda verificação de igualdade
nula contém a variável errada.
A expressão
V3022 é sempre falsa. DataFactoryClient.Encrypt.cs 37 (DataFactory)
public virtual string OnPremisesEncryptString(....) { .... if ( linkedServiceType == LinkedServiceType.OnPremisesSqlLinkedService && linkedServiceType == LinkedServiceType.OnPremisesOracleLinkedService && linkedServiceType == LinkedServiceType.OnPremisesFileSystemLinkedService && (value == null || value.Length == 0)) { throw new ArgumentNullException("value"); } .... }
A verificação é inútil e uma exceção nunca será lançada. A condição requer a igualdade simultânea da variável
linkedServiceType para três valores diferentes. Os operadores && e || provavelmente estão confusos. Código corrigido:
if (( linkedServiceType == LinkedServiceType.OnPremisesSqlLinkedService || linkedServiceType == LinkedServiceType.OnPremisesOracleLinkedService || linkedServiceType == LinkedServiceType.OnPremisesFileSystemLinkedService) && (value == null || value.Length == 0)) ....
A expressão
V3022 'Ekus == null' é sempre falsa. PSKeyVaultCertificatePolicy.cs 129 (KeyVault)
internal CertificatePolicy ToCertificatePolicy() { .... if (Ekus != null) { x509CertificateProperties.Ekus = Ekus == null ? null : new List<string>(Ekus); } .... }
Verificação
supérflua da variável
Ekus para igualdade
nula . Provavelmente nada de errado, mas o código parece feio.
V3023 Considere inspecionar esta expressão. A expressão é excessiva ou contém uma impressão incorreta. PolicyRetentionObjects.cs 207 (RecoveryServices)
public virtual void Validate() { if (RetentionTimes == null || RetentionTimes.Count == 0 || RetentionTimes.Count != 1) { throw new ArgumentException( Resources.InvalidRetentionTimesInPolicyException); } }
Verificação excessiva ou condição incorreta. Verificar
RetentionTimes.Count == 0 não faz sentido, porque depois disso, verifique
RetentionTimes.Count! = 1 .
V3025 Formato incorreto. É esperado um número diferente de itens de formato ao chamar a função 'Format'. Argumentos não utilizados: this.ResourceGroupName. NewScheduledQueryRuleCommand.cs 117 (Monitor)
protected override void ProcessRecordInternal() { .... if (this.ShouldProcess(this.Name, string.Format("Creating Log Alert Rule '{0}' in resource group {0}", this.Name, this.ResourceGroupName))) { .... } .... }
Erro na cadeia de formatação. O qualificador
{0} é usado duas vezes, com dois argumentos passados para o método
Format . A opção correta:
if (this.ShouldProcess(this.Name, string.Format("Creating Log Alert Rule '{0}' in resource group {1}", this.Name, this.ResourceGroupName))) ....
Outro erro semelhante:
- V3025 Formato incorreto. É esperado um número diferente de itens de formato ao chamar a função 'Format'. Argumentos não utilizados: this.ResourceGroupName. RemoveScheduledQueryRuleCommand.cs 88 (Monitor)
V3042 Possível NullReferenceException. O '?' e '.' operadores são usados para acessar membros do objeto 'imageAndOsType' VirtualMachineScaleSetStrategy.cs 81 (Compute)
internal static ResourceConfig<VirtualMachineScaleSet> CreateVirtualMachineScaleSetConfig(...., ImageAndOsType imageAndOsType, ....) { .... VirtualMachineProfile = new VirtualMachineScaleSetVMProfile { OsProfile = new VirtualMachineScaleSetOSProfile { ...., WindowsConfiguration = imageAndOsType.CreateWindowsConfiguration(),
Ao criar um objeto
VirtualMachineScaleSetVMProfile , a variável
imageAndOsType é usada sem verificar se é
nulo . No entanto, ao criar o
VirtualMachineScaleSetStorageProfile , essa variável já é verificada usando o operador de acesso condicional e duas vezes. O código parece inseguro.
V3042 Possível NullReferenceException. O '?' e '.' operadores são usados para acessar membros do objeto 'existenteContacts' RemoveAzureKeyVaultCertificateContact.cs 123 (KeyVault)
public override void ExecuteCmdlet() { .... List<PSKeyVaultCertificateContact> existingContacts; try { existingContacts = this.DataServiceClient. GetCertificateContacts(VaultName)?.ToList(); } catch (KeyVaultErrorException exception) { .... existingContacts = null; } foreach (var email in EmailAddress) { existingContacts.RemoveAll(....);
Como no caso da execução normal, e como resultado do tratamento da exceção, a variável
existenteContacts pode ficar
nula , após o que o trabalho continuará. Além disso, no código, essa variável é usada sem qualquer verificação.
V3066 Possível ordem incorreta de argumentos passada para o método 'PersistSyncServerRegistration': 'storageSyncServiceUid' e 'discoveryUri'. EcsManagementInteropClient.cs 364 (StorageSync)
public class EcsManagementInteropClient : IEcsManagement { .... public int PersistSyncServerRegistration(....) { return m_managementObject.PersistSyncServerRegistration( serviceUri, subscriptionId, storageSyncServiceName, resourceGroupName, clusterId, clusterName, storageSyncServiceUid,
O analisador suspeitou que a ordem de transmissão de argumentos para o método
PersistSyncServerRegistration estivesse
confusa . Declaração do método:
public interface IEcsManagement : IDisposable { .... int PersistSyncServerRegistration( [In, MarshalAs(UnmanagedType.BStr)] string serviceUri, [In, MarshalAs(UnmanagedType.BStr)] string subscriptionId, [In, MarshalAs(UnmanagedType.BStr)] string storageSyncServiceName, [In, MarshalAs(UnmanagedType.BStr)] string resourceGroupName, [In, MarshalAs(UnmanagedType.BStr)] string clusterId, [In, MarshalAs(UnmanagedType.BStr)] string clusterName, [In, MarshalAs(UnmanagedType.BStr)] string discoveryUri,
De fato, algo está misturado aqui com os argumentos número sete e oito. A verificação do código pelo autor é necessária.
V3077 O configurador da propriedade 'GetGuid' não utiliza seu parâmetro 'value'. RecoveryServicesBackupCmdletBase.cs 54 (RecoveryServices)
public abstract class RecoveryServicesBackupCmdletBase : AzureRMCmdlet { .... static string _guid; protected static string GetGuid { get { return _guid; } set { _guid = Guid.NewGuid().ToString(); } } .... }
O setter não usa o parâmetro transmitido. Em vez disso, eles obtêm um novo GUID e o atribuem ao campo
_guid . Eu acho que a maioria dos leitores concorda que esse código parece pelo menos feio. Usar essa construção não é muito conveniente: para (re) inicializar a propriedade
GetGuid ,
você deve atribuir algum valor falso a ela, o que é completamente óbvio. Mas, acima de tudo, fiquei divertido no momento em que os próprios autores usam essa construção. Há apenas um lugar no código em que o
GetGuid funciona . Dê uma olhada:
public override void ExecuteCmdlet() { .... var itemResponse = ServiceClientAdapter.CreateOrUpdateProtectionIntent( GetGuid ?? Guid.NewGuid().ToString(), ....); .... }
Ótimo!
V3091 Análise empírica. É possível que um erro de digitação esteja presente dentro da string literal: "ID do grupo de gerenciamento". A palavra 'Id' é suspeita. Constants.cs 36 (Recursos)
public class HelpMessages { public const string SubscriptionId = "Subscription Id of the subscription associated with the management"; public const string GroupId = "Management Group Id";
O analisador indicou um possível erro na sequência atribuída para a constante
GroupName . A conclusão é baseada em uma análise empírica de outras atribuições, levando em consideração nomes de variáveis. Penso que, neste caso, o analisador está correto e o valor da constante
GroupName deve estar no formato "Nome do grupo de gerenciamento". Provavelmente o erro foi causado pelo fato de o valor da constante
GroupId ter sido
copiado , mas eles esqueceram de alterá-lo.
Outro erro semelhante:
- V3091 Análise empírica. É possível que um erro de digitação esteja presente dentro da string literal. A palavra 'Nome' é suspeita. ParamHelpMsgs.cs 153 (RecoveryServices)
V3093 O '|' O operador avalia os dois operandos. Talvez um curto-circuito '||' operador deve ser usado. PSKeyVaultCertificatePolicy.cs 114 (KeyVault)
internal CertificatePolicy ToCertificatePolicy() { .... if (!string.IsNullOrWhiteSpace(SubjectName) || DnsNames != null || Ekus != null || KeyUsage != null |
Há suspeita de que tenha sido cometido um erro, e o operador || também deve ser usado entre as últimas condições no bloco
if . A resposta exata, como muitas vezes acontece, só pode ser dada pelo desenvolvedor.
V3095 O objeto 'certificado' foi usado antes de ser verificado em relação a nulo. Verifique as linhas: 41, 43. CertificateInfo.cs 41 (Automação)
public CertificateInfo( ...., Azure.Management.Automation.Models.Certificate certificate) { .... this.Name = certificate.Name; if (certificate == null) return; .... }
Clássico O objeto é usado primeiro e somente então o link é verificado como
nulo . Encontramos esses erros com
muita frequência . Considere outro erro semelhante.
V3095 O objeto 'clusterCred' foi usado antes de ser verificado em relação a nulo. Verifique as linhas: 115, 118. InvokeHiveCommand.cs 115 (HDInsight)
public override void ExecuteCmdlet() { .... _credential = new BasicAuthenticationCloudCredentials { Username = clusterCred.UserName, Password = clusterCred.Password.ConvertToString() }; if (clusterConnection == null || clusterCred == null) .... }
E mais alguns erros semelhantes:
- V3095 O objeto '_profile' foi usado antes de ser verificado contra nulo. Verifique as linhas: 47, 49. RMProfileClient.cs 47 (Contas)
- V3095 O objeto 'this.LoadBalancer.BackendAddressPools' foi usado antes de ser verificado como nulo. Verifique as linhas: 56, 63. AddAzureRmLoadBalancerBackendAddressPoolConfigCommand.cs 56 (CognitiveServices)
- Em geral, no código do Azure PowerShell, encontrei muito mais erros do V3095 . Mas todos são bem parecidos, então não vou me debruçar sobre isso com mais detalhes.
V3125 O objeto 'startTime' foi usado após a verificação contra nulo. Verifique as linhas: 1752, 1738. AutomationPSClientDSC.cs 1752 (Automation)
private string GetNodeReportListFilterString( ...., DateTimeOffset? startTime, ...., DateTimeOffset? lastModifiedTime) { .... if (startTime.HasValue) { odataFilter.Add("properties/startTime ge " + this.FormatDateTime(startTime.Value));
Também é um tipo de erro bastante comum. A variável
startTime foi verificada quanto ao valor no primeiro uso. A próxima vez que você usar isso, não. Mas poderia ser ainda pior. Dê uma olhada no segundo bloco
se . Eu acho que não deve haver uma variável
startTime . Isso é indicado pela ausência de sua verificação quanto à presença de um valor antes do uso e pela sequência formada para passar ao método
Add . A primeira parte desta linha menciona outra variável (
lastModifiedTime ).
V3125 O objeto 'firstPage' foi usado depois de verificado contra nulo. Verifique as linhas: 113, 108. IntegrationAccountAgreementOperations.cs 113 (LogicApp)
public IList<IntegrationAccountAgreement> ListIntegrationAccountAgreements(....) { var compositeList = new List<IntegrationAccountAgreement>(); var firstPage = this.LogicManagementClient. IntegrationAccountAgreements.List(....); if (firstPage != null) { compositeList.AddRange(firstPage); } if (!string.IsNullOrEmpty(firstPage.NextPageLink))
Outro erro óbvio. A variável
firstPage é usada de maneira insegura, embora anteriormente no código haja um uso dessa variável com uma verificação preliminar de
null .
A V3125 no código do Azure PowerShell foi ainda mais
bem -
sucedida que a
V3095 descrita anteriormente. Todos eles também são do mesmo tipo. Acho que podemos nos limitar aos dois que examinamos.
V3137 A variável 'apiVersionSetId' é atribuída, mas não é usada no final da função. GetAzureApiManagementApiVersionSet.cs 69 (ApiManagement)
public String ApiVersionSetId { get; set; } .... public override void ExecuteApiManagementCmdlet() { .... string apiVersionSetId; if (ParameterSetName.Equals(ContextParameterSet)) { .... apiVersionSetId = ApiVersionSetId; } else { apiVersionSetId = ....; } if (string.IsNullOrEmpty(ApiVersionSetId))
O analisador relata que a variável local
apiVersionSetId foi inicializada, mas não foi usada. Frequentemente, esse padrão indica um erro. Penso que, neste caso, a probabilidade de erro é alta, dado que o nome da variável local
apiVersionSetId e o nome da propriedade
ApiVersionSetId diferem apenas no caso da primeira letra. Dê uma olhada no código. Após inicializar
apiVersionSetId (de uma maneira ou de outra), somente a propriedade
ApiVersionSetId é usada no código. Muito, muito suspeito.
V3137 A variável 'cacheId' é atribuída, mas não é usada no final da função. RemoveAzureApiManagementCache.cs 94 (ApiManagement)
public String CacheId { get; set; } .... public override void ExecuteApiManagementCmdlet() { .... string cacheId; if (....) { .... cacheId = InputObject.CacheId; } else if (....) { .... cacheId = cache.CacheId; } else { .... cacheId = CacheId; } var actionDescription = string.Format(...., CacheId);
A situação, quase exatamente repetindo o anteriormente considerado. A variável local
cacheId não é usada após a inicialização. Em vez disso, eles usam uma propriedade com um nome muito semelhante,
CacheId . Não sei, talvez esse seja um padrão entre os desenvolvedores do Azure PowerShell. Mas parece um erro.
V3143 O parâmetro 'value' é reescrito dentro de um
configurador de propriedades e não é usado depois disso. NewAzureIntegrationAccountPartnerCommand.cs 67 (LogicApp)
[Parameter(Mandatory = false, HelpMessage = "The integration account partner type.", ValueFromPipelineByPropertyName = false)] [ValidateSet("B2B", IgnoreCase = false)] [ValidateNotNullOrEmpty] public string PartnerType { get { return this.partnerType; } set { value = this.partnerType; }
O campo
partnerType é declarado assim:
Ao contrário do nome da solução na qual esse erro foi detectado (LogicApp), não vejo a lógica aqui. Usar
valor em um setter para gravação não é uma ocorrência tão rara, mas, neste caso, estamos falando em perder o valor original. Parece estranho. O código tem um único acesso de leitura a essa propriedade. Talvez você deva novamente procurar aconselhamento especializado. Talvez eu não entenda alguma coisa. O fato é que conheci mais alguns dos mesmos padrões:
- V3143 O parâmetro 'value' é reescrito dentro de um configurador de propriedades e não é usado depois disso. NewAzureIntegrationAccountSchemaCommand.cs 79 (LogicApp)
- V3143 O parâmetro 'value' é reescrito dentro de um configurador de propriedades e não é usado depois disso. NewAzureIntegrationAccountSchemaCommand.cs 87 (LogicApp)
- V3143 O parâmetro 'value' é reescrito dentro de um configurador de propriedades e não é usado depois disso. UpdateAzureIntegrationAccountPartnerCommand.cs 67 (LogicApp)
- V3143 O parâmetro 'value' é reescrito dentro de um configurador de propriedades e não é usado depois disso. UpdateAzureIntegrationAccountSchemaCommand.cs 80 (LogicApp)
- V3143 O parâmetro 'value' é reescrito dentro de um configurador de propriedades e não é usado depois disso. UpdateAzureIntegrationAccountSchemaCommand.cs 88 (LogicApp)
Conclusão
Esses são todos os bugs interessantes encontrados no código do Azure PowerShell.
Entusiastas e apenas interessados, sugiro realizar um estudo independente de erros no código deste (ou de qualquer outro) projeto. Eu provavelmente poderia ter perdido outra coisa interessante. Para fazer isso, basta baixar e instalar o PVS-Studio .Obrigado pela leitura. Um código sem código!
Se você deseja compartilhar este artigo com um público que fala inglês, use o link para a tradução: Sergey Khrenov.
Azure PowerShell: Principalmente inofensivo .