診斷訊息
- 診斷
- abi_specific_integer_invalid
- abi_specific_integer_mapping_extra
- abi_specific_integer_mapping_missing
- abi_specific_integer_mapping_unsupported
- 抽象_
欄位_ 初始化器 - 抽象_
sealed_ 類別 - 抽象_
父類別_ 成員_ 參考 - 不明確的_
匯出 - 不明確的_
擴充功能_ 成員_ 存取 - 不明確的_
匯入 - 不明確的_
set或_ map_ 字面值_兩者皆是 - 不明確的_
set或_ map_ 字面值_兩者擇一 - 指標_
欄位上的_ 註解 - 引數必須是常數
- 引數必須是原生
- 引數類型不可賦值
- 引數類型不可賦值給錯誤處理常式
- 重新導向建構子中的_
assert - 資源目錄不存在
- 資源不存在
- 資源欄位不是清單
- 資源遺失路徑
- 資源不是字串
- 資源不是字串或 Map
- 資源路徑不是字串
- 請勿儲存的賦值
- 賦值給_
const - 賦值給_
final - 賦值給_
final_ 區域變數 - 賦值給沒有_
setter的_ final - 賦值給函式
- 賦值給方法
- 賦值給類型
- 錯誤情境中的_
async_ for-in - 延遲_
區域變數_ 初始化器中的_ await - 不相容類型的_
await - 函式主體可能正常完成
- 函式主體可能正常完成_
catchError - 函式主體可能正常完成_可為 Null
- switch_
成員上的_ break_ 標籤 - 內建_
識別項作為類型 - 宣告中的內建_
識別項 - case_
區塊未終止 - case_
運算式類型實作了_ equals - case_
運算式類型不是_ switch_ 運算式子類型 - 從可為 Null 的轉換永遠失敗
- 從_
null的轉換永遠失敗 - 轉換為非類型
- 類別用作混入
- 來自延遲載入程式庫的集合元素
- 複合實作了_
Finalizable - 具體類別具有列舉_
超介面 - 具有抽象成員的具體類別
- 建構子與靜態成員衝突
- 泛型介面衝突
- 類型變數與容器衝突
- 類型變數與成員衝突
- 常數模式永遠不符合值類型
- 具有非常數運算式的常數模式
- const_
建構子參數類型不符 - 由非常數初始化的_
const_ 建構子 - 具有非常數_
super的_ const_ 建構子 - 具有非_
final_ 欄位的_ const_ 建構子 - const_
延遲載入類別 - 使用非常數值初始化的_
const - 來自延遲載入程式庫的非常數值初始化的_
const - const_
實例欄位 - const_
map_ 金鑰不是基本相等性 - const_
未初始化 - const_
set_ 元素不是基本相等性 - const_
spread預期是清單或_ set - const_
spread預期是_ map - const_
搭配非_ const - const_
搭配非常數引數 - 具有類型參數的_
const - continue_
標籤無效 - struct或_
union的建立 - 使用非類型建立
- 無效程式碼
- 無效程式碼_catch後面的_
catch - 無效程式碼_on_
catch_ 子類型 - 無效_
null_ 感知_ 運算式 - 預設清單建構子
- 函式類型中的預設值
- 重新導向_
factory_ 建構子中的預設值 - 必要參數的預設值
- 擴充功能的延遲載入匯入
- 明確未賦值的_
late_ 區域變數 - 相依性欄位不是_
map - 已淘汰的冒號作為預設值
- 已淘汰的匯出使用
- 已淘汰的欄位
- 已淘汰的成員使用
- 來自相同套件的已淘汰成員使用
- 註解參考中已淘汰的_
new - 函式已淘汰的子類型
- 不允許的類型具現化運算式
- 除法最佳化
- 重複的建構子
- 重複的定義
- 重複的匯出
- 重複的欄位形式參數
- 重複的欄位名稱
- 重複的隱藏名稱
- 重複的_
ignore - 重複的匯入
- 重複的具名引數
- 重複的_
part - 模式賦值變數重複
- 模式欄位重複
- 模式中重複的其餘元素
- 重複的顯示名稱
- 重複的變數模式
- 空的_
map_ 模式 - 具有逗號的空記錄字面值
- 空的記錄類型具名欄位清單
- 具有逗號的空記錄類型
- 空的_
struct - 列舉常數與封閉項名稱相同
- 具有非常數建構子的列舉常數
- 具有實例變數的列舉混入
- 具有抽象成員的列舉
- 具有名稱值的列舉
- const_
set中相等的元素 - set中相等的元素
- const_
map中相等的金鑰 - map中相等的金鑰
- map_
模式中相等的金鑰 - 預期一個清單模式類型引數
- 預期一個清單類型引數
- 預期一個_
set類型引數 - 預期兩個_
map_ 模式類型引數 - 預期兩個_
map類型引數 - 匯出內部程式庫
- 匯出舊版符號
- 匯出非程式庫
- map中的運算式
- 擴充非類別
- 擴充功能作為運算式
- 擴充功能衝突的靜態和實例
- 擴充功能宣告抽象成員
- 擴充功能宣告建構子
- 擴充功能宣告實例欄位
- 擴充功能宣告物件成員
- 擴充功能覆寫存取靜態成員
- 擴充功能覆寫引數不可賦值
- 沒有存取的擴充功能覆寫
- 具有串聯的擴充功能覆寫
- 具有_
super_ 形式參數的擴充功能類型建構子 - 具有_
super_ 調用的擴充功能類型建構子 - 擴充功能類型宣告實例欄位
- 擴充功能類型宣告物件成員
- 擴充功能類型實作了不允許的類型
- 擴充功能類型實作了自身
- 擴充功能類型實作了非超類型
- 擴充功能類型實作了表示法非超類型
- 擴充功能類型繼承的成員衝突
- 擴充功能類型表示法取決於自身
- 擴充功能類型表示法類型為底部
- 具有抽象成員的擴充功能類型
- 具有初始化器的外部
- struct_
欄位上多餘的註解 - 額外的位置引數
- 額外的位置引數可能是具名的
- carray額外的大小註解
- ffi_native無效的重複預設資源
- ffi_native無效的多個註解
- ffi_native必須是外部的
- ffi_native非預期的參數數量
- ffi_native具有接收器的非預期參數數量
- 由多個初始化器初始化的欄位
- 在初始化器和宣告中初始化的欄位
- 在參數和初始化器中初始化的欄位
- 欄位初始化器_
factory_ 建構子 - struct中的欄位初始化器
- 欄位初始化器不可賦值
- 建構子外部的欄位初始化器
- 欄位初始化器重新導向建構子
- 欄位初始化形式參數不可賦值
- 具有初始化器的_
struct中的欄位 - struct中的欄位必須是外部的
- 在宣告和建構子中初始化的_
final - final_
未初始化 - final_
未初始化_建構子 - flutter_
欄位不是_ map - for-in_
的無效元素類型 - for-in_
的無效類型 - 具有_
const_ 變數的_ for-in - dynamic上的泛型方法類型具現化
- 泛型_
struct_ 子類別 - getter不是_
setter類型的子類型 - 非法的_
async_ 產生器傳回類型 - 非法的_
async傳回類型 - 非法的具體列舉成員
- 非法的列舉值
- 非法的_
sync_ 產生器傳回類型 - 實作非類別
- 重複實作
- 實作父類別
- 隱含_
super_ 初始化器遺失引數 - 初始化器中隱含的_
this_ 參考 - 具有載入函式的延遲載入程式庫匯入
- 匯入內部程式庫
- 將舊版程式庫匯入至空值安全程式庫
- 匯入非程式庫
- 不一致的繼承
- 不一致的語言版本覆寫
- 不一致的模式變數邏輯或
- 不存在欄位的初始化器
- 靜態欄位的初始化器
- 不存在欄位的初始化形式參數
- 實例存取靜態成員
- 來自_
factory的實例成員存取 - 來自靜態的實例成員存取
- 具現化抽象類別
- 具現化列舉
- 類型別名展開為類型參數
- 整數字面值作為雙精度浮點數不精確
- 整數字面值超出範圍
- 無效的註解
- 來自延遲載入程式庫的無效註解常數值
- 來自延遲載入程式庫的無效註解
- 無效的註解目標
- 無效的賦值
- 無效的相依性
- 無效的例外值
- 無效的內部元素匯出
- 間接無效的內部元素匯出
- 無效的擴充功能引數計數
- 無效的_
factory_ 方法宣告 - 無效的_
factory_ 方法實作 - 無效的_
factory_ 名稱不是類別 - 無效的欄位名稱
- struct中無效的欄位類型
- 無效的實作覆寫
- 無效的內嵌函式類型
- 無效的內部註解
- 無效的語言版本覆寫
- 無效的字面值註解
- 建構子上無效的修飾詞
- setter上無效的修飾詞
- 無效的非虛擬註解
- 無效的_
null_ 感知運算子 - 無效的覆寫
- 無效的非虛擬成員覆寫
- 共用_
case_ 範圍中無效的模式變數 - 無效的平台欄位
- 對產生器列舉建構子的無效參考
- 對_
this的無效參考 - catchError的無效傳回類型
- 無效的_
sealed_ 註解 - 無效的_
super_ 形式參數位置 - const_
字面值中無效的類型引數 - 無效的_
URI - 在擴充功能中無效地使用_
covariant - 無效地使用內部成員
- 無效地使用_
null值 - 在程式庫外部無效地使用類型
- 無效地使用可見以進行覆寫的成員
- 無效地使用可見以進行測試的成員
- 無效的可見性註解
- 無效的可見以進行覆寫的註解
- 無效的可見於範本外部的註解
- 沒有呼叫的擴充功能調用
- 非函式的調用
- 非函式運算式的調用
- 外部範圍中的標籤
- 未定義的標籤
- 具有_
const_ 建構子的_ late_ final_ 欄位 - 已賦值的_
late_ final_ 區域變數 - leaf_
呼叫不得傳回控制代碼 - leaf_
呼叫不得採用控制代碼 - 清單元素類型不可賦值
- main第一個位置參數類型
- main具有必要的具名參數
- main具有過多必要的位置參數
- main不是函式
- map中沒有_
map_ 條目 - map_
金鑰類型不可賦值 - map_
值類型不可賦值 - struct_
欄位上不符的註解 - struct_
欄位上遺失的註解 - 遺失的_
Dart程式庫 - 參數遺失預設值
- 遺失的相依性
- switch中遺失的列舉常數
- 遺失的例外值
- struct中遺失的欄位類型
- 遺失的名稱
- 遺失的具名模式欄位名稱
- 遺失必須覆寫的覆寫
- 遺失的必要引數
- 遺失的必要參數
- 遺失的傳回
- carray遺失大小註解
- 遺失的變數模式
- mixin應用具體父類別叫用成員類型
- mixin應用未實作介面
- mixin應用沒有具體的父類別叫用成員
- mixin類別宣告擴充非物件
- mixin類別宣告建構子
- mixin繼承自非物件
- mixin具現化
- mixin的非類別
- sealed_
類別上的_ mixin - mixin_
父類別限制延遲載入類別 - mixin_
父類別限制非介面 - 多個重新導向建構子調用
- 多個_
super_ 初始化器 - 必須是原生函式類型
- 必須是子類型
- 必須是不可變的
- 必須呼叫_
super - 必須傳回_
void - 名稱不是字串
- 原生欄位無效的類型
- 原生欄位遺失類型
- 原生欄位不是靜態的
- 原生函式遺失類型
- 負數變數維度
- 具有未定義建構子預設值的_
new - 非抽象類別繼承抽象成員
- 非布林條件
- 非布林運算式
- 非布林否定運算式
- 非布林運算元
- 非常數註解建構子
- 非常數_
case_ 運算式 - 來自延遲載入程式庫的非常數_
case_ 運算式 - 非常數預設值
- 來自延遲載入程式庫的非常數預設值
- 非常數清單元素
- 非常數_
map_ 元素 - 非常數_
map_ 金鑰 - 非常數_
map_ 模式金鑰 - 非常數_
map_ 值 - 非常數關係模式運算式
- 非常數_
set_ 元素 - 非常數類型引數
- const_
參數的非常數引數 - 字面值建構子的非常數呼叫
- 非常數產生器列舉建構子
- 表示法類型中非變異數類型參數位置
- 非詳盡的_
switch_ 運算式 - 非詳盡的_
switch_ 陳述式 - 列舉中非_
final_ 欄位 - 非產生器建構子
- 非產生器隱含建構子
- 指標的非原生函式類型引數
- 非正數陣列維度
- 非尺寸類型引數
- 非同步_
factory - 非類型作為類型引數
- catch_
子句中的非類型 - 運算子的非_
void傳回 - setter的非_
void傳回 - 未賦值的潛在非可為 Null 區域變數
- 不是類型
- 不是二元運算子
- 位置引數不足
- 未初始化的非可為 Null 實例欄位
- 未初始化的非可為 Null 變數
- 非可迭代的展開
- 非_
map_ 展開 - 沒有註解建構子引數
- 沒有組合的_
super_ 簽章 - 父類別中沒有產生器建構子
- catch_
子句中的可為 Null 類型 - extends_
子句中的可為 Null 類型 - implements_
子句中的可為 Null 類型 - on_
子句中的可為 Null 類型 - with_
子句中的可為 Null 類型 - null引數給非_
null類型 - null檢查永遠失敗
- 已過時的冒號作為預設值
- on重複
- 運算子中的選用參數
- 非覆寫成員的覆寫
- packed註解
- packed註解對齊
- 不同程式庫的_
part_ of - 非_
part的_ part_ of - 未命名程式庫的_
part_ of - 路徑不存在
- 路徑不是_
POSIX - 路徑_
pubspec不存在 - 模式賦值不是區域變數
- 來自延遲載入程式庫的模式常數
- 不可反駁情境中的模式類型不符
- 防護中的模式變數賦值
- 不允許的平台值
- 物件模式中的位置欄位
- 具有位置引數的位置_
super_ 形式參數 - 前置詞與最上層成員衝突
- 前置詞識別項後面沒有點
- 本機宣告遮蔽的前置詞
- mixin應用中的私有衝突
- 私有選用參數
- 私有_
setter - 讀取可能未賦值的_
final - 記錄字面值一個位置沒有尾隨逗號
- 記錄類型一個位置沒有尾隨逗號
- 遞迴編譯時期常數
- 遞迴建構子重新導向
- 遞迴介面繼承
- 非重新宣告成員的重新宣告
- 重新導向產生器至遺失的建構子
- 重新導向產生器至非產生器建構子
- 重新導向至抽象類別建構子
- 重新導向至無效函式類型
- 重新導向至無效傳回類型
- 重新導向至遺失的建構子
- 重新導向至非類別
- 重新導向至非_
const_ 建構子 - 重新導向至類型別名展開為類型參數
- 在宣告之前參考
- 不可反駁情境中的可反駁模式
- 關係模式運算元類型不可賦值
- 關係模式運算子傳回類型不可賦值給布林值
- map_
模式中的其餘元素 - catch外部的_
rethrow - 產生器建構子中的傳回
- 產生器中的傳回
- 請勿儲存的傳回
- 無效類型的傳回
- 來自封閉項的無效類型傳回
- 沒有值的傳回
- 從核心匯出的_
sdk_ 版本_ async - const_
情境中作為運算式的_ sdk_ 版本 - const_
情境中的_ sdk_ 版本布林運算子 - sdk_
版本建構子拆解 - const_
情境中的_ sdk_ 版本_ eq_eq運算子 - sdk_
版本擴充功能方法 - sdk_
版本_ gt_gt_gt運算子 - const_
情境中的_ sdk_ 版本_ is運算式 - sdk_
版本_ never - sdk_
版本_ set_ 字面值 - sdk_
版本_ UI作為程式碼 - const_
情境中的_ sdk_ 版本_ UI作為程式碼 - set_
元素類型不可賦值 - 共用的延遲載入前置詞
- 大小註解維度
- 靜態存取實例成員
- base或_
final的子類型不是_ base、final或_ sealed - 延遲載入類別的子類型
- 不允許類型的子類型
- ffi_
類別的子類型 - sealed_
類別的子類型 - struct_
類別的子類型 - 超類型展開為類型參數
- super_
形式參數類型不是關聯項的子類型 - 沒有關聯具名的_
super_ 形式參數 - 沒有關聯位置的_
super_ 形式參數 - super_
調用不是最後一個 - 列舉建構子中的_
super - 擴充功能中的_
super - 擴充功能類型中的_
super - 無效情境中的_
super - 重新導向建構子中的_
super - switch_
case正常完成 - switch_
運算式不可賦值 - 抽象類別的產生器建構子的拆解
- 註解中的文字方向碼點
- 字面值中的文字方向碼點
- 無效類型的拋出
- 最上層循環
- 類型別名無法參考自身
- 類型註解延遲載入類別
- 類型引數不符合界限
- 使用_
null的類型檢查 - 靜態參考的類型參數
- 其界限的超類型的類型參數
- 使用非類型的類型測試
- 使用未定義名稱的類型測試
- 未檢查地使用可為 Null 值
- 未定義的註解
- 未定義的類別
- 初始化器中未定義的建構子
- 未定義的列舉常數
- 未定義的列舉建構子
- 未定義的擴充功能_
getter - 未定義的擴充功能方法
- 未定義的擴充功能運算子
- 未定義的擴充功能_
setter - 未定義的函式
- 未定義的_
getter - 未定義的隱藏名稱
- 未定義的識別項
- 未定義的識別項_
await - 未定義的方法
- 未定義的具名參數
- 未定義的運算子
- 未定義的前置詞名稱
- 未定義的參考參數
- 未定義的_
setter - 未定義的顯示名稱
- 未定義的_
super_ 成員 - 未知的平台
- 不必要的轉換
- 不必要的開發相依性
- 不必要的_
final - 不必要的匯入
- 不必要的_
NaN比較 - 不必要的非空值斷言
- 不必要的_
noSuchMethod - 不必要的_
null_ 斷言模式 - 不必要的_
null_ 檢查模式 - 不必要的_
null比較 - 不必要的問號
- 不必要的_
set_ 字面值 - 不必要的類型檢查
- 對非本機靜態成員的不合格參考
- 對擴充類型靜態成員的不合格參考
- 無法連線的_
switch_ case - 無法連線的_
switch_ default - 未使用的_
catch_ 子句 - 未使用的_
catch堆疊 - 未使用的元素
- 未使用的元素參數
- 未使用的欄位
- 未使用的匯入
- 未使用的標籤
- 未使用的區域變數
- 未使用的結果
- 未使用的顯示名稱
- URI不存在
- 文件匯入中_
URI不存在 - URI尚未產生
- 具有內插的_
URI - 原生擴充功能的使用
- void結果的使用
- 列舉中的值宣告
- 變長陣列不是最後一個
- 宣告情境中的變數模式關鍵字
- 變數類型不符
- 工作區欄位不是清單
- 工作區值不是字串
- 工作區值不是子目錄
- 運算子的參數數量錯誤
- setter的參數數量錯誤
- 類型引數數量錯誤
- 建構子的類型引數數量錯誤
- 列舉的類型引數數量錯誤
- 擴充功能的類型引數數量錯誤
- 方法的類型引數數量錯誤
- 非產生器中的_
yield - 無效類型的_
yield - 永遠宣告傳回類型
- 永遠將控制主體放在新行
- 永遠將必要的具名參數放在最前面
- 永遠使用套件匯入
- 註解覆寫
- 避免空的_
else - 避免在_
forEach呼叫中使用函式字面值 - 避免_
FutureOr <void> - 避免初始化為_
null - 避免_
print - 避免相對_
lib匯入 - 避免重新命名方法參數
- 避免_
setter的傳回類型 - 避免為_
void傳回_ null - 避免遮蔽類型參數
- 避免在運算式陳述式中使用單一串聯
- 避免緩慢的_
async_ IO - 避免類型轉字串
- 避免類型作為參數名稱
- 避免不必要的容器
- 避免在_
Flutter中使用網頁程式庫 - 僅等待_
Future - 駝峰式命名擴充功能
- 駝峰式命名類型
- 取消訂閱
- 關閉接收器
- 集合方法不相關的類型
- 常數識別項名稱
- finally中的控制流程
- 流程控制結構中的大括號
- 懸掛的程式庫文件註解
- 依賴參考的套件
- 空的_
catch區塊 - 空的建構子主體
- 空的陳述式
- 檔案名稱
- hash和_
equals - 實作匯入
- 隱含呼叫拆解
- 使用_
JS互通類型進行無效的執行階段檢查 - 無效地使用請勿提交的成員
- 程式庫註解
- 程式庫名稱
- 程式庫前置詞
- 公用_
API中的程式庫私有類型 - 僅限字面值的布林運算式
- 清單中沒有相鄰字串
- 沒有重複的_
case值 - 程式庫前置詞沒有前導底線
- 本機識別項沒有前導底線
- createState中沒有邏輯
- 沒有萬用字元變數使用
- 非常數識別項名稱
- 可為 Null 類型參數的空值檢查
- 覆寫的欄位
- 套件名稱
- 套件前置詞程式庫名稱
- 偏好相鄰字串串連
- 偏好集合字面值
- 偏好條件賦值
- 偏好_
const_ 建構子 - 偏好不可變物件中的_
const_ 建構子 - 偏好_
const_ 宣告 - 偏好_
const_ 字面值以建立不可變物件 - 偏好_
contains - 偏好雙引號
- 偏好_
final_ 欄位 - 偏好使用_
for元素而不是_ mapFromIterable - 偏好函式宣告而不是變數
- 偏好泛型函式類型別名
- 偏好_
if_ null運算子 - 偏好初始化形式參數
- 偏好內嵌的_
add - 偏好內插而不是撰寫字串
- 偏好_
isEmpty - 偏好_
isNotEmpty - 偏好_
is_ not運算子 - 偏好_
Iterable .whereType - 偏好_
null_ 感知運算子 - 偏好相對匯入
- 偏好單引號
- 偏好為未初始化的變數輸入類型
- 偏好_
void而不是_ null - 提供已淘汰訊息
- 遞迴式_
getter - 安全_
pubspec_ 網址 - 用於空白的_
尺寸_ 方塊 - 尺寸_
方塊_ 收縮_ 展開 - 用於_
文件_ 註解的斜線 - 排序_
子項_ 屬性_ 最後 - 排序_
建構子_ 優先 - 排序_
pub_ 相依性 - 排序_
未命名_ 建構子_ 優先 - 等於中的_
測試_ 類型 - 在_
finally中拋出 - 類型_
初始化_ 形式 - 常數_
模式中的類型_ 字面值 - 未等待的_
Future - 文件_
註解中非預期的_ HTML - 字串_
內插中不必要的_ 大括號 - 不必要的_
const - 不必要的_
建構子_ 名稱 - 不必要的_
final - 不必要的_
getter_ 和_ setter - 不必要的_
ignore - 不必要的_
lambda - 不必要的_
late - 不必要的_
library_ 名稱 - 不必要的_
new - 不必要的_
null_ 感知_ 賦值 - if_
null_ 運算子中不必要的_ null - final_
變數_ 宣告不必要的_ 可為 Null - 不必要的_
覆寫 - 不必要的_
括號 - 不必要的_
原始_ 字串 - 不必要的_
陳述式 - 不必要的_
字串_ 跳脫字元 - 不必要的_
字串_ 內插 - 不必要的_
this - 展開中不必要的_
to_ list - 不必要的_
底線 - 不相關的_
類型_ 相等性_ 檢查 - 不安全的_
變異數 - 同步使用_
BuildContext - 使用_
彩色_ 方塊 - 使用_
裝飾_ 方塊 - Flutter_
顏色使用完整的_ 十六進位_ 值 - 參數使用_
函式_ 類型_ 語法 - 使用_
if_ null將_ null轉換為_ 布林值 - 在_
widget_ 建構子中使用_ key - 私有_
欄位和_ 變數使用_ late - 使用_
具名_ 常數 - 使用_
null_ 感知_ 元素 - 使用_
原始_ 字串 - 盡可能使用_
rethrow - 使用_
setter來變更_ 屬性 - 使用_
字串_ 緩衝區 - 在_
part_ of_ 指示詞中使用_ 字串 - 使用_
super_ 參數 - 使用_
截斷_ 除法 - 有效的_
正規表示式 - void_
檢查
本頁列出 Dart 分析器產生的診斷訊息,其中詳細說明這些訊息的意義以及如何修正程式碼。如需分析器的詳細資訊,請參閱自訂靜態分析。
診斷
#分析器會針對不符合語言規格或可能以非預期方式運作的程式碼產生下列診斷訊息。
abi_specific_integer_invalid
#擴充 'AbiSpecificInteger' 的類別必須剛好有一個 const 建構子、沒有其他成員,且沒有類型參數。
描述
#當擴充 AbiSpecificInteger
的類別不符合以下所有需求時,分析器會產生此診斷訊息
- 必須剛好有一個建構子
- 建構子必須標記為
const
- 除了建構子之外,不得有任何其他成員
- 不得有任何類型參數
範例
#下列程式碼會產生此診斷訊息,因為類別 C
未定義 const 建構子
import 'dart:ffi';
@AbiSpecificIntegerMapping({Abi.macosX64 : Int8()})
final class C extends AbiSpecificInteger {
}
下列程式碼會產生此診斷訊息,因為建構子不是 const
建構子
import 'dart:ffi';
@AbiSpecificIntegerMapping({Abi.macosX64 : Int8()})
final class C extends AbiSpecificInteger {
C();
}
下列程式碼會產生此診斷訊息,因為類別 C
定義了多個建構子
import 'dart:ffi';
@AbiSpecificIntegerMapping({Abi.macosX64 : Int8()})
final class C extends AbiSpecificInteger {
const C.zero();
const C.one();
}
下列程式碼會產生此診斷訊息,因為類別 C
定義了一個欄位
import 'dart:ffi';
@AbiSpecificIntegerMapping({Abi.macosX64 : Int8()})
final class C extends AbiSpecificInteger {
final int i;
const C(this.i);
}
下列程式碼會產生此診斷訊息,因為類別 C
具有類型參數
import 'dart:ffi';
@AbiSpecificIntegerMapping({Abi.macosX64 : Int8()})
final class C<T> extends AbiSpecificInteger { // type parameters
const C();
}
常見修正方式
#變更類別,使其符合沒有類型參數且只有一個成員(即 const
建構子)的需求
import 'dart:ffi';
@AbiSpecificIntegerMapping({Abi.macosX64 : Int8()})
final class C extends AbiSpecificInteger {
const C();
}
abi_specific_integer_mapping_extra
#擴充 'AbiSpecificInteger' 的類別必須剛好有一個 'AbiSpecificIntegerMapping' 註解,指定從 ABI 到具有固定大小的 'NativeType' 整數的對應。
描述
#當擴充 AbiSpecificInteger
的類別具有多個 AbiSpecificIntegerMapping
註解時,分析器會產生此診斷訊息。
範例
#下列程式碼會產生此診斷訊息,因為類別 C
上有兩個 AbiSpecificIntegerMapping
註解
import 'dart:ffi';
@AbiSpecificIntegerMapping({Abi.macosX64 : Int8()})
@AbiSpecificIntegerMapping({Abi.linuxX64 : Uint16()})
final class C extends AbiSpecificInteger {
const C();
}
常見修正方式
#移除除一個註解之外的所有註解,並視情況合併引數
import 'dart:ffi';
@AbiSpecificIntegerMapping({Abi.macosX64 : Int8(), Abi.linuxX64 : Uint16()})
final class C extends AbiSpecificInteger {
const C();
}
abi_specific_integer_mapping_missing
#擴充 'AbiSpecificInteger' 的類別必須剛好有一個 'AbiSpecificIntegerMapping' 註解,指定從 ABI 到具有固定大小的 'NativeType' 整數的對應。
描述
#當擴充 AbiSpecificInteger
的類別沒有 AbiSpecificIntegerMapping
註解時,分析器會產生此診斷訊息。
範例
#下列程式碼會產生此診斷訊息,因為類別 C
上沒有 AbiSpecificIntegerMapping
註解
import 'dart:ffi';
final class C extends AbiSpecificInteger {
const C();
}
常見修正方式
#將 AbiSpecificIntegerMapping
註解新增至類別
import 'dart:ffi';
@AbiSpecificIntegerMapping({Abi.macosX64 : Int8()})
final class C extends AbiSpecificInteger {
const C();
}
abi_specific_integer_mapping_unsupported
#對 '{0}' 的無效對應;僅支援對 'Int8'、'Int16'、'Int32'、'Int64'、'Uint8'、'Uint16'、'UInt32' 和 'Uint64' 的對應。
描述
#當 AbiSpecificIntegerMapping
註解的 map 引數中的值不是下列整數類型之一時,分析器會產生此診斷訊息
Int8
Int16
Int32
Int64
Uint8
Uint16
UInt32
Uint64
範例
#下列程式碼會產生此診斷訊息,因為 map 條目的值是 Array<Uint8>
,這不是有效的整數類型
import 'dart:ffi';
@AbiSpecificIntegerMapping({Abi.macosX64 : Array<Uint8>(4)})
final class C extends AbiSpecificInteger {
const C();
}
常見修正方式
#使用其中一個有效類型作為 map 中的值
import 'dart:ffi';
@AbiSpecificIntegerMapping({Abi.macosX64 : Int8()})
final class C extends AbiSpecificInteger {
const C();
}
抽象_欄位_初始化器
#抽象欄位不能有初始化器。
描述
#當具有 abstract
修飾詞的欄位也有初始化器時,分析器會產生此診斷訊息。
範例
#下列程式碼會產生此診斷訊息,因為 f
標記為 abstract
且具有初始化器
abstract class C {
abstract int f = 0;
}
下列程式碼會產生此診斷訊息,因為 f
標記為 abstract
且建構子中有初始化器
abstract class C {
abstract int f;
C() : f = 0;
}
常見修正方式
#如果欄位必須是抽象的,則移除初始化器
abstract class C {
abstract int f;
}
如果欄位不需要是抽象的,則移除關鍵字
abstract class C {
int f = 0;
}
抽象_sealed_類別
#'sealed' 類別不能標記為 'abstract',因為它已經隱含地是抽象的。
描述
#當使用 abstract
修飾詞和 sealed
修飾詞宣告類別時,分析器會產生此診斷訊息。密封類別隱含地是抽象的,因此不允許明確地同時使用這兩個修飾詞。
範例
#下列程式碼會產生此診斷訊息,因為類別 C
同時使用 abstract
和 sealed
宣告
abstract sealed class C {}
常見修正方式
#如果類別應該是抽象的但不是密封的,則移除 sealed
修飾詞
abstract class C {}
如果類別應該同時是抽象的和密封的,則移除 abstract
修飾詞
sealed class C {}
抽象_父類別_成員_參考
#父類型中的 {0} '{1}' 永遠是抽象的。
描述
#當使用 super
參考繼承的成員,但父類別鏈中沒有成員的具體實作時,分析器會產生此診斷訊息。抽象成員無法叫用。
範例
#下列程式碼會產生此診斷訊息,因為 B
未繼承 a
的具體實作
abstract class A {
int get a;
}
class B extends A {
int get a => super.a;
}
常見修正方式
#移除抽象成員的叫用,可能以叫用具體成員取代。
不明確的_匯出
#名稱 '{0}' 定義於程式庫 '{1}' 和 '{2}' 中。
描述
#當兩個或多個匯出指示詞導致從多個程式庫匯出相同的名稱時,分析器會產生此診斷訊息。
範例
#假設檔案 a.dart
包含
class C {}
以及檔案 b.dart
包含
class C {}
下列程式碼會產生此診斷訊息,因為名稱 C
同時從 a.dart
和 b.dart
匯出
export 'a.dart';
export 'b.dart';
常見修正方式
#如果其中一個程式庫中的名稱都不需要匯出,則移除不必要的匯出指示詞
export 'a.dart';
如果所有匯出指示詞都是必要的,則在除一個指示詞之外的所有指示詞中隱藏名稱
export 'a.dart';
export 'b.dart' hide C;
不明確的_擴充功能_成員_存取
#名為 '{0}' 的成員定義於 '{1}' 和 '{2}' 中,且兩者都不更具體。
名為 '{0}' 的成員定義於 {1} 中,且沒有任何一個更具體。
描述
#當程式碼參考物件的成員(例如,o.m()
或 o.m
或 o[i]
),其中 o
的靜態類型未宣告成員(例如 m
或 []
)時,分析器會嘗試在擴充功能中尋找成員。例如,如果成員是 m
,則分析器會尋找宣告名為 m
的成員且具有 o
的靜態類型可賦值給的擴充類型之擴充功能。當範圍內有多個此類擴充功能時,會選取擴充類型最具體的擴充功能。
當沒有任何擴充功能的擴充類型比所有其他擴充功能的擴充類型更具體時,分析器會產生此診斷訊息,使得成員的參考不明確。
範例
#下列程式碼會產生此診斷訊息,因為無法在 E1
中的成員和 E2
中的成員之間做出選擇
extension E1 on String {
int get charCount => 1;
}
extension E2 on String {
int get charCount => 2;
}
void f(String s) {
print(s.charCount);
}
常見修正方式
#如果您不需要兩個擴充功能,則可以刪除或隱藏其中一個。
如果您需要兩個擴充功能,則使用擴充功能覆寫明確選取您想要使用的擴充功能
extension E1 on String {
int get charCount => length;
}
extension E2 on String {
int get charCount => length;
}
void f(String s) {
print(E2(s).charCount);
}
不明確的_匯入
#名稱 '{0}' 定義於程式庫 {1} 中。
描述
#當參考的名稱在兩個或多個匯入的程式庫中宣告時,分析器會產生此診斷訊息。
範例
#假設一個程式庫 (a.dart
) 定義一個類別 (本範例中的 C
)
class A {}
class C {}
以及一個程式庫 (b.dart
) 定義一個具有相同名稱的不同類別
class B {}
class C {}
下列程式碼會產生此診斷訊息
import 'a.dart';
import 'b.dart';
void f(C c1, C c2) {}
常見修正方式
#如果不需要任何程式庫,則移除其匯入指示詞
import 'a.dart';
void f(C c1, C c2) {}
如果名稱仍然由多個程式庫定義,則將 hide
子句新增至除一個程式庫之外的所有程式庫的匯入指示詞
import 'a.dart' hide C;
import 'b.dart';
void f(C c1, C c2) {}
如果您必須能夠參考多個這些類型,則為每個匯入指示詞新增前置詞,並使用適當的前置詞限定參考
import 'a.dart' as a;
import 'b.dart' as b;
void f(a.C c1, b.C c2) {}
不明確的_set或_map_字面值_兩者皆是
#字面值不能是 map 或 set,因為它至少包含一個字面值 map 條目或展開運算子展開 'Map',以及至少一個不是這些的元素。
描述
#由於 map 和 set 字面值使用相同的分隔符號({
和 }
),因此分析器會查看類型引數和元素,以判斷您意指的字面值種類。當沒有類型引數時,分析器會使用元素的類型。如果所有元素都是字面值 map 條目,且所有展開運算子都在展開 Map
,則它是 Map
。如果沒有任何元素是字面值 map 條目,且所有展開運算子都在展開 Iterable
,則它是 Set
。如果這兩者都不成立,則不明確。
當至少一個元素是字面值 map 條目或展開運算子展開 Map
,且至少一個元素不是這些時,分析器會產生此診斷訊息,使得分析器無法判斷您正在撰寫 map 字面值還是 set 字面值。
範例
#下列程式碼會產生此診斷訊息
union(Map<String, String> a, List<String> b, Map<String, String> c) =>
{...a, ...b, ...c};
清單 b
只能展開到 set 中,而 map a
和 c
只能展開到 map 中,且字面值不能同時是兩者。
常見修正方式
#有兩種常見的方法可以解決這個問題。第一種方法是移除所有種類的展開元素,使元素保持一致。在這種情況下,這可能意味著移除列表,並決定如何處理現在未使用的參數。
union(Map<String, String> a, List<String> b, Map<String, String> c) =>
{...a, ...c};
第二種解決方法是將其中一種元素更改為與其他元素一致的元素。例如,您可以將列表的元素添加為鍵,並將它們映射到自身。
union(Map<String, String> a, List<String> b, Map<String, String> c) =>
{...a, for (String s in b) s: s, ...c};
不明確的_set或_map_字面值_兩者擇一
#這個字面值必須是 map 或 set,但元素沒有足夠的資訊來進行型別推斷。
描述
#因為 map 和 set 字面值使用相同的分隔符號 ({
和 }
),所以分析器會查看型別引數和元素,以判斷您指的是哪種字面值。當沒有型別引數且所有元素都是展開元素(這在兩種字面值中都允許)時,分析器會使用正在展開的表達式的型別。如果所有表達式都具有 Iterable
型別,則它是 set 字面值;如果它們都具有 Map
型別,則它是 map 字面值。
當展開的表達式都沒有允許分析器判斷您正在編寫 map 字面值還是 set 字面值的型別時,就會產生此診斷訊息。
範例
#下列程式碼會產生此診斷訊息
union(a, b) => {...a, ...b};
問題發生是因為沒有型別引數,並且沒有關於 a
或 b
型別的資訊。
常見修正方式
#有三種常見的方法可以解決這個問題。第一種方法是向字面值添加型別引數。例如,如果字面值旨在成為 map 字面值,您可以這樣寫
union(a, b) => <String, String>{...a, ...b};
第二種解決方法是添加型別資訊,使表達式具有 Iterable
型別或 Map
型別。您可以添加顯式轉換,或者在這種情況下,為兩個參數的宣告添加型別。
union(List<int> a, List<int> b) => {...a, ...b};
第三種解決方法是添加上下文資訊。在這種情況下,這意味著為函數添加回傳型別。
Set<String> union(a, b) => {...a, ...b};
在其他情況下,您可能在其他地方添加型別。例如,假設原始程式碼如下所示
union(a, b) {
var x = {...a, ...b};
return x;
}
您可以像這樣在 x
上添加型別註解
union(a, b) {
Map<String, String> x = {...a, ...b};
return x;
}
指標_欄位上的_註解
#結構 (struct) 類別中型別為 'Pointer' 的欄位不應有任何註解。
描述
#當在 Struct
子類別中宣告且型別為 Pointer
的欄位也帶有相關的註解時,分析器會產生此診斷訊息。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼產生此診斷訊息,因為欄位 p
的型別為 Pointer
,並且在 Struct
的子類別中宣告,但帶有註解 @Double()
import 'dart:ffi';
final class C extends Struct {
@Double()
external Pointer<Int8> p;
}
常見修正方式
#從欄位中移除註解
import 'dart:ffi';
final class C extends Struct {
external Pointer<Int8> p;
}
引數必須是常數
#引數 '{0}' 必須是常數。
描述
#當 Pointer.asFunction
或 DynamicLibrary.lookupFunction
的調用具有 isLeaf
引數,但其值不是常數表達式時,分析器會產生此診斷訊息。
當 Pointer.fromFunction
或 NativeCallable.isolateLocal
的調用具有 exceptionalReturn
引數,但其值不是常數表達式時,分析器也會產生此診斷訊息。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼產生此診斷訊息,因為 isLeaf
引數的值是一個參數,因此不是常數。
import 'dart:ffi';
int Function(int) fromPointer(
Pointer<NativeFunction<Int8 Function(Int8)>> p, bool isLeaf) {
return p.asFunction(isLeaf: isLeaf);
}
常見修正方式
#如果有適合使用的常數,則將引數替換為常數。
import 'dart:ffi';
const isLeaf = false;
int Function(int) fromPointer(Pointer<NativeFunction<Int8 Function(Int8)>> p) {
return p.asFunction(isLeaf: isLeaf);
}
如果沒有適合的常數,則將引數替換為布林字面值。
import 'dart:ffi';
int Function(int) fromPointer(Pointer<NativeFunction<Int8 Function(Int8)>> p) {
return p.asFunction(isLeaf: true);
}
引數必須是原生
#'Native.addressOf' 的引數必須使用 @Native 註解。
描述
#當傳遞給 Native.addressOf
的引數未使用 Native
註解時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 addressOf
的引數是一個字串,而不是欄位,而字串不能被註解。
import 'dart:ffi';
@Native<Void Function()>()
external void f();
void g() {
print(Native.addressOf('f'));
}
以下程式碼產生此診斷訊息,因為函數 f
被傳遞給 addressOf
,但未註解為 Native
。
import 'dart:ffi';
external void f();
void g() {
print(Native.addressOf<NativeFunction<Void Function()>>(f));
}
常見修正方式
#如果引數既不是欄位也不是函數,則將引數替換為使用 Native
註解的欄位或函數。
import 'dart:ffi';
@Native<Void Function()>()
external void f();
void g() {
print(Native.addressOf<NativeFunction<Void Function()>>(f));
}
如果引數是欄位或函數,則使用 Native
註解欄位或函數。
import 'dart:ffi';
@Native<Void Function()>()
external void f();
void g() {
print(Native.addressOf<NativeFunction<Void Function()>>(f));
}
引數類型不可賦值
#引數型別 '{0}' 無法指派給參數型別 '{1}'。{2}
描述
#當引數的靜態型別無法指派給對應參數的靜態型別時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 num
無法指派給 String
。
String f(String x) => x;
String g(num y) => f(y);
常見修正方式
#如果可能,請重寫程式碼,使靜態型別可指派。在上面的範例中,您或許可以更改參數 y
的型別。
String f(String x) => x;
String g(String y) => f(y);
如果無法進行該修正,則添加程式碼來處理引數值不是所需型別的情況。一種方法是將其他型別強制轉換為所需的型別。
String f(String x) => x;
String g(num y) => f(y.toString());
另一種方法是添加顯式型別測試和後備程式碼。
String f(String x) => x;
String g(Object y) => f(y is String ? y : '');
如果您認為引數的執行時期型別將始終與參數的靜態型別相同,並且您願意承擔在錯誤時執行時期拋出例外狀況的風險,則添加顯式轉換。
String f(String x) => x;
String g(num y) => f(y as String);
引數類型不可賦值給錯誤處理常式
#引數型別 '{0}' 無法指派給參數型別 '{1} Function(Object)' 或 '{1} Function(Object, StackTrace)'。
描述
#當 Future.catchError
的調用具有一個引數,該引數是一個函數,其參數與在調用函數時將傳遞給函數的引數不相容時,分析器會產生此診斷訊息。 catchError
第一個引數的靜態型別只是 Function
,即使傳入的函數預期具有型別為 Object
的單個參數,或型別為 Object
和 StackTrace
的兩個參數。
範例
#以下程式碼產生此診斷訊息,因為傳遞給 catchError
的閉包不接受任何參數,但函數需要至少接受一個參數。
void f(Future<int> f) {
f.catchError(() => 0);
}
以下程式碼產生此診斷訊息,因為傳遞給 catchError
的閉包接受三個參數,但它不能有超過兩個的必要參數。
void f(Future<int> f) {
f.catchError((one, two, three) => 0);
}
以下程式碼產生此診斷訊息,因為即使傳遞給 catchError
的閉包接受一個參數,但閉包的型別與 Object
不相容。
void f(Future<int> f) {
f.catchError((String error) => 0);
}
常見修正方式
#更改傳遞給 catchError
的函數,使其具有一個或兩個必要參數,並且參數具有所需的型別。
void f(Future<int> f) {
f.catchError((Object error) => 0);
}
重新導向建構子中的_assert
#重新導向建構子不能有 'assert' 初始化子。
描述
#當重新導向建構子(重新導向到同一類別中另一個建構子的建構子)在初始化列表中具有 assert 時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為未命名的建構子是重新導向建構子,並且在初始化列表中也具有 assert。
class C {
C(int x) : assert(x > 0), this.name();
C.name() {}
}
常見修正方式
#如果不需要 assert,則將其移除。
class C {
C(int x) : this.name();
C.name() {}
}
如果需要 assert,則將建構子轉換為工廠建構子。
class C {
factory C(int x) {
assert(x > 0);
return C.name();
}
C.name() {}
}
資源目錄不存在
#資源目錄 '{0}' 不存在。
描述
#當資源列表包含引用不存在目錄的值時,分析器會產生此診斷訊息。
範例
#假設目錄 assets
不存在,則以下程式碼產生此診斷訊息,因為它被列為包含資源的目錄。
name: example
flutter:
assets:
- assets/
常見修正方式
#如果路徑正確,則在該路徑建立一個目錄。
如果路徑不正確,則更改路徑以匹配包含資源的目錄的路徑。
資源不存在
#資源檔案 '{0}' 不存在。
描述
#當資源列表包含引用不存在檔案的值時,分析器會產生此診斷訊息。
範例
#假設檔案 doesNotExist.gif
不存在,則以下程式碼產生此診斷訊息,因為它被列為資源。
name: example
flutter:
assets:
- doesNotExist.gif
常見修正方式
#如果路徑正確,則在該路徑建立一個檔案。
如果路徑不正確,則更改路徑以匹配包含資源的檔案的路徑。
資源欄位不是清單
#'assets' 欄位的值預期為相對檔案路徑的列表。
描述
#當 assets
鍵的值不是列表時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 assets
鍵的值是一個字串,但預期為列表。
name: example
flutter:
assets: assets/
常見修正方式
#更改資源列表的值,使其成為列表。
name: example
flutter:
assets:
- assets/
資源遺失路徑
#資源映射條目必須包含 'path' 欄位。
描述
#當資源映射缺少 path
值時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為資源映射缺少 path
值。
name: example
flutter:
assets:
- flavors:
- premium
常見修正方式
#更改資源映射,使其包含具有字串值(有效的 POSIX 風格檔案路徑)的 path
欄位。
name: example
flutter:
assets:
- path: assets/image.gif
flavors:
- premium
資源不是字串
#資源必須是檔案路徑(字串)。
描述
#當 assets
列表包含不是字串的值時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 assets
列表包含一個映射。
name: example
flutter:
assets:
- image.gif: true
常見修正方式
#更改 assets
列表,使其僅包含有效的 POSIX 風格檔案路徑。
name: example
flutter:
assets:
- assets/image.gif
資源不是字串或 Map
#資源值必須是檔案路徑(字串)或映射。
描述
#當資源值不是字串或映射時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為資源值是一個列表。
name: example
flutter:
assets:
- [one, two, three]
常見修正方式
#如果您需要指定的不僅僅是資源的路徑,則將該值替換為具有 path
鍵(有效的 POSIX 風格檔案路徑)的映射。
name: example
flutter:
assets:
- path: assets/image.gif
flavors:
- premium
如果您只需要指定路徑,則將該值替換為資源的路徑(有效的 POSIX 風格檔案路徑)。
name: example
flutter:
assets:
- assets/image.gif
資源路徑不是字串
#資源路徑必須是檔案路徑(字串)。
描述
#當資源映射包含不是字串的 path
值時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為資源映射包含一個 path
值,該值是一個列表。
name: example
flutter:
assets:
- path: [one, two, three]
flavors:
- premium
常見修正方式
#更改 asset
映射,使其包含一個 path
值,該值是一個字串(有效的 POSIX 風格檔案路徑)。
name: example
flutter:
assets:
- path: image.gif
flavors:
- premium
請勿儲存的賦值
#'{0}' 標記為 'doNotStore',不應指派給欄位或頂層變數。
描述
#當函數(包括方法和 getter)的值(明確或隱含地標記為 doNotStore
註解)儲存在欄位或頂層變數中時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為函數 f
的值正在儲存在頂層變數 x
中。
import 'package:meta/meta.dart';
@doNotStore
int f() => 1;
var x = f();
常見修正方式
#將對欄位或變數的引用替換為產生值的函數的調用。
賦值給_const
#常數變數在初始化後不能被指派值。
描述
#當分析器找到對具有 const
修飾符的頂層變數、靜態欄位或區域變數的指派時,會產生此診斷訊息。編譯時期常數的值在執行時期不能被更改。
範例
#以下程式碼產生此診斷訊息,因為即使 c
具有 const
修飾符,仍被指派值。
const c = 0;
void f() {
c = 1;
print(c);
}
常見修正方式
#如果變數必須可指派,則移除 const
修飾符。
var c = 0;
void f() {
c = 1;
print(c);
}
如果常數不應被更改,則移除指派,或使用區域變數代替對常數的引用。
const c = 0;
void f() {
var v = 1;
print(v);
}
賦值給_final
#'{0}' 不能用作 setter,因為它是 final。
描述
#當分析器找到 setter 的調用,但由於同名的欄位宣告為 final
或 const
而沒有 setter 時,會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 v
是 final。
class C {
final v = 0;
}
f(C c) {
c.v = 1;
}
常見修正方式
#如果您需要能夠設定欄位的值,則從欄位中移除修飾符 final
。
class C {
int v = 0;
}
f(C c) {
c.v = 1;
}
賦值給_final_區域變數
#final 變數 '{0}' 只能設定一次。
描述
#當宣告為 final 的區域變數在初始化後被指派值時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 x
是 final,因此在初始化後不能再指派值給它。
void f() {
final x = 0;
x = 3;
print(x);
}
常見修正方式
#移除關鍵字 final
,如果沒有型別註解,則替換為 var
。
void f() {
var x = 0;
x = 3;
print(x);
}
賦值給沒有_setter的_final
#類別 '{1}' 中沒有名為 '{0}' 的 setter。
描述
#當找到對 setter 的引用時,分析器會產生此診斷訊息;該型別沒有定義 setter;但存在具有相同名稱的 getter。
範例
#以下程式碼產生此診斷訊息,因為 C
中沒有名為 x
的 setter,但存在名為 x
的 getter。
class C {
int get x => 0;
set y(int p) {}
}
void f(C c) {
c.x = 1;
}
常見修正方式
#如果您想調用現有的 setter,則更正名稱。
class C {
int get x => 0;
set y(int p) {}
}
void f(C c) {
c.y = 1;
}
如果您想調用 setter 但它尚不存在,則宣告它。
class C {
int get x => 0;
set x(int p) {}
set y(int p) {}
}
void f(C c) {
c.x = 1;
}
賦值給函式
#函數不能被指派值。
描述
#當函數的名稱出現在指派表達式的左側時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為對函數 f
的指派無效。
void f() {}
void g() {
f = () {};
}
常見修正方式
#如果右側應該指派給其他東西,例如區域變數,則更改左側。
void f() {}
void g() {
var x = () {};
print(x);
}
如果目的是更改函數的實作,則定義一個函數值變數而不是函數。
void Function() f = () {};
void g() {
f = () {};
}
賦值給方法
#方法不能被指派值。
描述
#當指派的目標是方法時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 f
不能被指派值,因為它是一個方法。
class C {
void f() {}
void g() {
f = null;
}
}
常見修正方式
#重寫程式碼,使其沒有對方法的指派。
賦值給類型
#型別不能被指派值。
描述
#當型別名稱的名稱出現在指派表達式的左側時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為對類別 C
的指派無效。
class C {}
void f() {
C = null;
}
常見修正方式
#如果右側應該指派給其他東西,例如區域變數,則更改左側。
void f() {}
void g() {
var c = null;
print(c);
}
錯誤情境中的_async_for-in
#async for-in 迴圈只能在 async 函數中使用。
描述
#當在函數或方法中找到 async for-in 迴圈,但函數或方法的主體未標記為 async
或 async*
時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 f
的主體未標記為 async
或 async*
,但 f
包含 async for-in 迴圈。
void f(list) {
await for (var e in list) {
print(e);
}
}
常見修正方式
#如果函數應回傳 Future
,則將主體標記為 async
。
Future<void> f(list) async {
await for (var e in list) {
print(e);
}
}
如果函數應回傳值的 Stream
,則將主體標記為 async*
。
Stream<void> f(list) async* {
await for (var e in list) {
print(e);
}
}
如果函數應為同步的,則移除迴圈之前的 await
。
void f(list) {
for (var e in list) {
print(e);
}
}
延遲_區域變數_初始化器中的_await
#'await' 表達式不能用於 'late' 區域變數的初始化子。
描述
#當具有 late
修飾符的區域變數在其初始化子中使用 await
表達式時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 await
表達式用於 v
的初始化子中,而 v
是一個標記為 late
的區域變數。
Future<int> f() async {
late var v = await 42;
return v;
}
常見修正方式
#如果可以重寫初始化子以不使用 await
,則重寫它。
Future<int> f() async {
late var v = 42;
return v;
}
如果無法重寫初始化子,則移除 late
修飾符。
Future<int> f() async {
var v = await 42;
return v;
}
不相容類型的_await
#'await' 表達式不能用於擴展型別 (extension type) 的表達式,該擴展型別不是 'Future' 的子型別。
描述
#當 await
表達式中表達式的型別是擴展型別,並且該擴展型別不是 Future
的子類別時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為擴展型別 E
不是 Future
的子類別。
extension type E(int i) {}
void f(E e) async {
await e;
}
常見修正方式
#如果擴展型別定義正確,則移除 await
。
extension type E(int i) {}
void f(E e) {
e;
}
如果擴展型別旨在是可等待的,則將 Future
(或 Future
的子型別)添加到 implements
子句中(如果尚不存在 implements
子句,則添加一個),並使表示型別匹配。
extension type E(Future<int> i) implements Future<int> {}
void f(E e) async {
await e;
}
函式主體可能正常完成
#主體可能會正常完成,導致回傳 'null',但回傳型別 '{0}' 是潛在的非可空型別。
描述
#當方法或函數具有 潛在的非可空 回傳型別,但如果控制流程到達函數末尾,則會隱含地回傳 null
時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為方法 m
在方法末尾插入了 null
的隱含回傳,但該方法被宣告為不回傳 null
。
class C {
int m(int t) {
print(t);
}
}
以下程式碼產生此診斷訊息,因為方法 m
在方法末尾插入了 null
的隱含回傳,但由於類別 C
可以使用非可空型別引數實例化,因此該方法實際上被宣告為不回傳 null
。
class C<T> {
T m(T t) {
print(t);
}
}
常見修正方式
#如果存在可以回傳的合理值,則在方法末尾添加 return
語句。
class C<T> {
T m(T t) {
print(t);
return t;
}
}
如果方法不會到達隱含回傳,則在方法末尾添加 throw
。
class C<T> {
T m(T t) {
print(t);
throw '';
}
}
如果方法有意在末尾回傳 null
,則在方法末尾添加顯式的 null
回傳,並更改回傳型別,使其可以有效地回傳 null
。
class C<T> {
T? m(T t) {
print(t);
return null;
}
}
函式主體可能正常完成_catchError
#此 'onError' 處理器必須回傳可指派給 '{0}' 的值,但結束時未回傳值。
描述
#當傳遞給 Future.catchError
方法的 onError
參數的閉包需要回傳非 null
值(由於 Future
的型別引數),但可能會隱含地回傳 null
時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為傳遞給 catchError
方法的閉包需要回傳 int
,但並未以顯式的 return
結束,導致它隱含地回傳 null
。
void g(Future<int> f) {
f.catchError((e, st) {});
}
常見修正方式
#如果閉包有時應該回傳非 null
值,則向閉包添加顯式回傳。
void g(Future<int> f) {
f.catchError((e, st) {
return -1;
});
}
如果閉包應始終回傳 null
,則將 Future
的型別引數更改為 void
或 Null
。
void g(Future<void> f) {
f.catchError((e, st) {});
}
函式主體可能正常完成_可為 Null
#此函數具有可空的回傳型別 '{0}',但結束時未回傳值。
描述
#當方法或函數可以通過到達末尾而隱含地回傳 null
時,分析器會產生此診斷訊息。雖然這是有效的 Dart 程式碼,但最好明確地回傳 null
。
範例
#以下程式碼產生此診斷訊息,因為函數 f
隱含地回傳 null
。
String? f() {}
常見修正方式
#如果有意回傳 null
,則使其明確。
String? f() {
return null;
}
如果函數應該沿該路徑回傳非 null 值,則添加遺失的 return 語句。
String? f() {
return '';
}
switch_成員上的_break_標籤
#break 標籤解析為 'case' 或 'default' 語句。
描述
#當 switch 語句內 case 子句中的 break 具有與另一個 case 子句關聯的標籤時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為標籤 l
與 0
的 case 子句關聯。
void f(int i) {
switch (i) {
l: case 0:
break;
case 1:
break l;
}
}
常見修正方式
#如果目的是將控制權轉移到 switch 之後的語句,則從 break 語句中移除標籤。
void f(int i) {
switch (i) {
case 0:
break;
case 1:
break;
}
}
如果目的是將控制權轉移到不同的 case 區塊,則使用 continue
而不是 break
。
void f(int i) {
switch (i) {
l: case 0:
break;
case 1:
continue l;
}
}
內建_識別項作為類型
#內建識別符 '{0}' 不能用作型別。
描述
#當在預期型別名稱的地方使用內建識別符時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 import
不能用作型別,因為它是一個內建識別符。
import<int> x;
常見修正方式
#將內建識別符替換為有效型別的名稱。
List<int> x;
宣告中的內建_識別項
#內建識別符 '{0}' 不能用作前綴名稱。
內建識別符 '{0}' 不能用作型別名稱。
內建識別符 '{0}' 不能用作型別參數名稱。
內建識別符 '{0}' 不能用作 typedef 名稱。
內建識別符 '{0}' 不能用作擴展名稱。
內建識別符 '{0}' 不能用作擴展型別名稱。
描述
#當類別、擴展、mixin、typedef、型別參數或 import 前綴的宣告中使用的名稱是內建識別符時,分析器會產生此診斷訊息。內建識別符不能用於命名任何這些種類的宣告。
範例
#以下程式碼產生此診斷訊息,因為 mixin
是一個內建識別符。
extension mixin on int {}
常見修正方式
#為宣告選擇不同的名稱。
case_區塊未終止
#'case' 的最後一個語句應為 'break'、'continue'、'rethrow'、'return' 或 'throw'。
描述
#當 case
區塊中的最後一個語句不是必需的終止符之一時,分析器會產生此診斷訊息:break
、continue
、rethrow
、return
或 throw
。
範例
#以下程式碼產生此診斷訊息,因為 case
區塊以指派結束。
void f(int x) {
switch (x) {
case 0:
x += 2;
default:
x += 1;
}
}
常見修正方式
#添加必需的終止符之一。
void f(int x) {
switch (x) {
case 0:
x += 2;
break;
default:
x += 1;
}
}
case_運算式類型實作了_equals
#switch case 表達式型別 '{0}' 不能覆寫 '==' 運算子。
描述
#當關鍵字 case
後面的表達式的型別具有 ==
運算子的實作,而不是 Object
中的實作時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為關鍵字 case
後面的表達式 (C(0)
) 具有型別 C
,並且類別 C
覆寫了 ==
運算子。
class C {
final int value;
const C(this.value);
bool operator ==(Object other) {
return false;
}
}
void f(C c) {
switch (c) {
case C(0):
break;
}
}
常見修正方式
#如果沒有強烈的理由不這樣做,則重寫程式碼以使用 if-else 結構。
class C {
final int value;
const C(this.value);
bool operator ==(Object other) {
return false;
}
}
void f(C c) {
if (c == C(0)) {
// ...
}
}
如果您無法重寫 switch 語句,並且 ==
的實作不是必要的,則將其移除。
class C {
final int value;
const C(this.value);
}
void f(C c) {
switch (c) {
case C(0):
break;
}
}
如果您無法重寫 switch 語句,也無法移除 ==
的定義,則找到一些其他可以用於控制 switch 的值。
class C {
final int value;
const C(this.value);
bool operator ==(Object other) {
return false;
}
}
void f(C c) {
switch (c.value) {
case 0:
break;
}
}
case_運算式類型不是_switch_運算式子類型
#switch case 表達式型別 '{0}' 必須是 switch 表達式型別 '{1}' 的子型別。
描述
#當 switch
語句中 case
後面的表達式的靜態型別不是 switch
後面的表達式的靜態型別的子型別時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 1
是 int
,它不是 String
(s
的型別)的子型別。
void f(String s) {
switch (s) {
case 1:
break;
}
}
常見修正方式
#如果 case
表達式的值錯誤,則更改 case
表達式,使其具有所需的型別。
void f(String s) {
switch (s) {
case '1':
break;
}
}
如果 case
表達式的值正確,則更改 switch
表達式以具有所需的型別。
void f(int s) {
switch (s) {
case 1:
break;
}
}
從可為 Null 的轉換永遠失敗
#此轉換始終會拋出例外狀況,因為可空的區域變數 '{0}' 未指派值。
描述
#當具有可空型別的區域變數尚未指派值,並且被轉換為非可空型別時,分析器會產生此診斷訊息。由於變數尚未指派值,因此它具有預設值 null
,導致轉換拋出例外狀況。
範例
#以下程式碼產生此診斷訊息,因為變數 x
在已知具有值 null
時被轉換為非可空型別 (int
)。
void f() {
num? x;
x as int;
print(x);
}
常見修正方式
#如果預期變數在轉換之前具有值,則添加初始化子或指派。
void f() {
num? x = 3;
x as int;
print(x);
}
如果預期變數不會被指派值,則移除轉換。
void f() {
num? x;
print(x);
}
從_null的轉換永遠失敗
#此轉換始終會拋出例外狀況,因為表達式始終評估為 'null'。
描述
#當型別為 Null
的表達式被轉換為非可空型別時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為已知 n
始終為 null
,但它被轉換為非可空型別。
void f(Null n) {
n as int;
}
常見修正方式
#移除不必要的轉換。
void f(Null n) {
n;
}
轉換為非類型
#名稱 '{0}' 不是型別,因此不能在 'as' 表達式中使用。
描述
#當轉換表達式中 as
後面的名稱被定義為型別以外的其他東西時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 x
是一個變數,而不是型別。
num x = 0;
int y = x as x;
常見修正方式
#將名稱替換為型別的名稱。
num x = 0;
int y = x as int;
類別用作混入
#類別 '{0}' 不能用作 mixin,因為它既不是 mixin 類別也不是 mixin。
描述
#當既不是 mixin class
也不是 mixin
的類別在 with
子句中使用時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為類別 M
被用作 mixin,但它未定義為 mixin class
。
class M {}
class C with M {}
常見修正方式
#如果類別可以是純 mixin,則將 class
更改為 mixin
。
mixin M {}
class C with M {}
如果類別需要既是類別又是 mixin,則添加 mixin
。
mixin class M {}
class C with M {}
來自延遲載入程式庫的集合元素
#來自延遲載入程式庫的常數值不能用作 'const' map 字面值中的鍵。
來自延遲載入程式庫的常數值不能用作 'const' 建構子中的值。
來自延遲載入程式庫的常數值不能用作 'const' list 字面值中的值。
來自延遲載入程式庫的常數值不能用作 'const' map 字面值中的值。
來自延遲載入程式庫的常數值不能用作 'const' set 字面值中的值。
描述
#當集合字面值(明確地(因為它以 const
關鍵字作為前綴)或隱含地(因為它出現在 常數上下文 中))包含在使用延遲載入 import 匯入的程式庫中宣告的值時,分析器會產生此診斷訊息。常數在編譯時期評估,而來自延遲載入程式庫的值在編譯時期不可用。
有關更多資訊,請查看 延遲載入程式庫。
範例
#給定一個檔案 a.dart
,它定義了常數 zero
const zero = 0;
以下程式碼產生此診斷訊息,因為常數列表字面值包含 a.zero
,它是使用 deferred
import 匯入的。
import 'a.dart' deferred as a;
var l = const [a.zero];
常見修正方式
#如果集合字面值不需要是常數,則移除 const
關鍵字。
import 'a.dart' deferred as a;
var l = [a.zero];
如果集合需要是常數,並且必須引用匯入的常數,則從 import 中移除關鍵字 deferred
。
import 'a.dart' as a;
var l = const [a.zero];
如果您不需要引用常數,則將其替換為合適的值。
var l = const [0];
複合實作了_Finalizable
#類別 '{0}' 無法實作 Finalizable。
描述
#當 Struct
或 Union
的子類別實作 Finalizable
時,分析器會產生此診斷訊息。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼產生此診斷訊息,因為類別 S
實作了 Finalizable
。
import 'dart:ffi';
final class S extends Struct implements Finalizable {
external Pointer notEmpty;
}
常見修正方式
#嘗試從類別中移除 implements 子句。
import 'dart:ffi';
final class S extends Struct {
external Pointer notEmpty;
}
具體類別具有列舉_超介面
#具體類別不能將 'Enum' 作為超介面。
描述
#當具體類別間接地將類別 Enum
作為超介面時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為具體類別 B
由於實作了 A
而將 Enum
作為超介面。
abstract class A implements Enum {}
class B implements A {}
常見修正方式
#如果實作的類別不是您想要實作的類別,則更改它。
abstract class A implements Enum {}
class B implements C {}
class C {}
如果可以更改實作的類別以不實作 Enum
,則執行此操作。
abstract class A {}
class B implements A {}
如果無法更改實作的類別以不實作 Enum
,則從 implements
子句中移除它。
abstract class A implements Enum {}
class B {}
具有抽象成員的具體類別
#'{0}' 必須具有方法主體,因為 '{1}' 不是抽象的。
描述
#當找到具體類別的成員沒有具體實作時,分析器會產生此診斷訊息。具體類別不允許包含抽象成員。
範例
#以下程式碼產生此診斷訊息,因為 m
是一個抽象方法,但 C
不是一個抽象類別。
class C {
void m();
}
常見修正方式
#如果建立類別的實例是有效的,則為成員提供實作。
class C {
void m() {}
}
如果建立類別的實例無效,則將類別標記為抽象的。
abstract class C {
void m();
}
建構子與靜態成員衝突
#'{0}' 不能用於命名此類別中的建構子和靜態欄位。
'{0}' 不能用於命名此類別中的建構子和靜態 getter。
'{0}' 不能用於命名此類別中的建構子和靜態方法。
'{0}' 不能用於命名此類別中的建構子和靜態 setter。
描述
#當具名建構子和靜態方法或靜態欄位具有相同的名稱時,分析器會產生此診斷訊息。兩者都使用類別的名稱進行存取,因此具有相同的名稱會使引用不明確。
範例
#以下程式碼產生此診斷訊息,因為靜態欄位 foo
和具名建構子 foo
具有相同的名稱。
class C {
C.foo();
static int foo = 0;
}
以下程式碼產生此診斷訊息,因為靜態方法 foo
和具名建構子 foo
具有相同的名稱。
class C {
C.foo();
static void foo() {}
}
常見修正方式
#重新命名成員或建構子。
泛型介面衝突
#類別 {0} '{1}' 無法同時實作 '{2}' 和 '{3}',因為型別引數不同。
描述
#當類別嘗試多次實作泛型介面,並且型別引數的值不相同時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 C
被定義為同時實作 I<int>
(因為它擴展了 A
)和 I<String>
(因為它實作了 B
),但 int
和 String
不是相同的型別。
class I<T> {}
class A implements I<int> {}
class B implements I<String> {}
class C extends A implements B {}
常見修正方式
#重新設計型別層次結構以避免這種情況。例如,您可以將一個或兩個繼承的型別設為泛型,以便 C
可以為兩個型別引數指定相同的型別。
class I<T> {}
class A<S> implements I<S> {}
class B implements I<String> {}
class C extends A<String> implements B {}
類型變數與容器衝突
#'{0}' 不能用於命名型別參數和定義型別參數的類別。
'{0}' 不能用於命名型別參數和定義型別參數的列舉。
'{0}' 不能用於命名型別參數和定義型別參數的擴展。
'{0}' 不能用於命名型別參數和定義型別參數的擴展型別。
'{0}' 不能用於命名型別參數和定義型別參數的 mixin。
描述
#當類別、mixin 或擴展宣告宣告的型別參數與宣告它的類別、mixin 或擴展具有相同的名稱時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為型別參數 C
與它所屬的類別 C
具有相同的名稱。
class C<C> {}
常見修正方式
#重新命名型別參數,或類別、mixin 或擴展。
class C<T> {}
類型變數與成員衝突
#'{0}' 不能用於命名型別參數和此類別中的成員。
'{0}' 不能用於命名型別參數和此列舉中的成員。
'{0}' 不能用於命名型別參數和此擴展型別中的成員。
'{0}' 不能用於命名型別參數和此擴展中的成員。
'{0}' 不能用於命名型別參數和此 mixin 中的成員。
描述
#當類別、mixin 或擴展宣告宣告的型別參數與宣告它的類別、mixin 或擴展的成員之一具有相同的名稱時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為型別參數 T
與欄位 T
具有相同的名稱。
class C<T> {
int T = 0;
}
常見修正方式
#重新命名型別參數或與之衝突的成員。
class C<T> {
int total = 0;
}
常數模式永遠不符合值類型
#符合的值類型 '{0}' 永遠無法等於類型為 '{1}' 的常數。
描述
#當常數模式永遠無法與其測試的值相符時,分析器會產生此診斷,因為已知常數的類型永遠不會與值的類型相符。
範例
#以下程式碼會產生此診斷,因為常數模式 (true)
的類型為 bool
,而要比對的值 (x
) 的類型為 int
,且布林值永遠無法與整數相符。
void f(int x) {
if (x case true) {}
}
常見修正方式
#如果值的類型正確,則重新撰寫模式以使其相容
void f(int x) {
if (x case 3) {}
}
如果常數的類型正確,則重新撰寫值以使其相容
void f(bool x) {
if (x case true) {}
}
具有非常數運算式的常數模式
#常數模式的運算式必須是有效的常數。
描述
#當常數模式具有不是有效常數的運算式時,分析器會產生此診斷。
範例
#以下程式碼會產生此診斷,因為常數模式 i
不是常數
void f(int e, int i) {
switch (e) {
case i:
break;
}
}
常見修正方式
#如果應該比對的值是已知的,則將運算式替換為常數
void f(int e, int i) {
switch (e) {
case 0:
break;
}
}
如果應該比對的值是未知的,則重新撰寫程式碼以不使用模式
void f(int e, int i) {
if (e == i) {}
}
const_建構子參數類型不符
#在常數建構函式中,類型為 '{0}' 的值無法指派給類型為 '{1}' 的參數。
描述
#當常數值的執行階段類型無法指派給常數建構函式參數的靜態類型時,分析器會產生此診斷。
範例
#以下程式碼會產生此診斷,因為 i
的執行階段類型為 int
,無法指派給 s
的靜態類型
class C {
final String s;
const C(this.s);
}
const dynamic i = 0;
void f() {
const C(i);
}
常見修正方式
#將正確類型的值傳遞給建構函式
class C {
final String s;
const C(this.s);
}
const dynamic i = 0;
void f() {
const C('$i');
}
由非常數初始化的_const_建構子
#因為欄位 '{0}' 是以非常數值初始化的,所以無法定義 'const' 建構函式。
描述
#當建構函式具有關鍵字 const
,但類別中的欄位卻初始化為非常數值時,分析器會產生此診斷。
範例
#以下程式碼會產生此診斷,因為欄位 s
是以非常數值初始化的
String x = '3';
class C {
final String s = x;
const C();
}
常見修正方式
#如果欄位可以初始化為常數值,則將初始化運算式變更為常數運算式
class C {
final String s = '3';
const C();
}
如果欄位無法初始化為常數值,則從建構函式中移除關鍵字 const
String x = '3';
class C {
final String s = x;
C();
}
具有非常數_super的_const_建構子
#常數建構函式無法呼叫 '{0}' 的非常數父類別建構函式。
描述
#當標記為 const
的建構函式從其父類別叫用未標記為 const
的建構函式時,分析器會產生此診斷。
範例
#以下程式碼會產生此診斷,因為 B
中的 const
建構函式從類別 A
叫用建構函式 nonConst
,而父類別建構函式不是 const
建構函式
class A {
const A();
A.nonConst();
}
class B extends A {
const B() : super.nonConst();
}
常見修正方式
#如果非得要叫用目前正在叫用的父類別建構函式,則從父類別叫用常數建構函式
class A {
const A();
A.nonConst();
}
class B extends A {
const B() : super();
}
如果非得要叫用目前的建構函式,而且您可以修改它,則將 const
新增至父類別中的建構函式
class A {
const A();
const A.nonConst();
}
class B extends A {
const B() : super.nonConst();
}
如果非得要叫用目前的建構函式,而且您無法修改它,則從子類別中的建構函式移除 const
class A {
const A();
A.nonConst();
}
class B extends A {
B() : super.nonConst();
}
具有非_final_欄位的_const_建構子
#無法為具有非 final 欄位的類別定義常數建構函式。
描述
#當建構函式標記為常數建構函式,但在具有至少一個非 final 實例欄位(直接或透過繼承)的類別中定義建構函式時,分析器會產生此診斷。
範例
#以下程式碼會產生此診斷,因為欄位 x
不是 final
class C {
int x;
const C(this.x);
}
常見修正方式
#如果可以將所有欄位標記為 final,請執行此操作
class C {
final int x;
const C(this.x);
}
如果無法將所有欄位標記為 final,則從建構函式中移除關鍵字 const
class C {
int x;
C(this.x);
}
const_延遲載入類別
#延遲類別無法以 'const' 建立。
描述
#當使用延遲匯入匯入的程式庫中的類別用於建立 const
物件時,分析器會產生此診斷。常數會在編譯時期評估,而延遲程式庫中的類別在編譯時期無法使用。
有關更多資訊,請查看 延遲載入程式庫。
範例
#以下程式碼會產生此診斷,因為它嘗試建立延遲程式庫中類別的 const
實例
import 'dart:convert' deferred as convert;
const json2 = convert.JsonCodec();
常見修正方式
#如果物件不需要是常數,則變更程式碼,使建立非常數實例
import 'dart:convert' deferred as convert;
final json2 = convert.JsonCodec();
如果物件必須是常數,則從匯入指示詞中移除 deferred
import 'dart:convert' as convert;
const json2 = convert.JsonCodec();
使用非常數值初始化的_const
#常數變數必須以常數值初始化。
描述
#當將靜態已知不是常數的值指派給宣告為 const
變數的變數時,分析器會產生此診斷。
範例
#以下程式碼會產生此診斷,因為 x
未宣告為 const
var x = 0;
const y = x;
常見修正方式
#如果可以將指派的值宣告為 const
,則變更宣告
const x = 0;
const y = x;
如果值無法宣告為 const
,則從變數中移除 const
修飾詞,可能會改用 final
var x = 0;
final y = x;
來自延遲載入程式庫的非常數值初始化的_const
#延遲程式庫中的常數值無法用於初始化 'const' 變數。
描述
#當使用從使用延遲匯入匯入的程式庫中的 const
變數初始化 const
變數時,分析器會產生此診斷。常數會在編譯時期評估,而延遲程式庫中的值在編譯時期無法使用。
有關更多資訊,請查看 延遲載入程式庫。
範例
#以下程式碼會產生此診斷,因為變數 pi
是使用程式庫 dart:math
中的常數 math.pi
初始化的,而 dart:math
是以延遲程式庫匯入的
import 'dart:math' deferred as math;
const pi = math.pi;
常見修正方式
#如果您需要參考從匯入程式庫中的常數值,則移除關鍵字 deferred
import 'dart:math' as math;
const pi = math.pi;
如果您不需要參考匯入的常數,則移除參考
const pi = 3.14;
const_實例欄位
#只有靜態欄位可以宣告為 const。
描述
#當實例欄位標記為 const 時,分析器會產生此診斷。
範例
#以下程式碼會產生此診斷,因為 f
是實例欄位
class C {
const int f = 3;
}
常見修正方式
#如果欄位需要是實例欄位,則移除關鍵字 const
,或將其替換為 final
class C {
final int f = 3;
}
如果欄位確實應該是 const 欄位,則使其成為靜態欄位
class C {
static const int f = 3;
}
const_map_金鑰不是基本相等性
#常數 Map 中索引鍵的類型無法覆寫 '==' 運算子或 'hashCode',但類別 '{0}' 卻覆寫了。
描述
#當用作常數 Map 實值中的索引鍵物件類別實作 ==
運算子、 getter hashCode
或兩者時,分析器會產生此診斷。常數 Map 的實作同時使用 ==
運算子和 hashCode
getter,因此除了從 Object
繼承的實作之外的任何實作,都需要在編譯時期執行任意程式碼,而這是 UnimplementedError。
範例
#以下程式碼會產生此診斷,因為常數 Map 包含類型為 C
的索引鍵,且類別 C
覆寫了 ==
的實作
class C {
const C();
bool operator ==(Object other) => true;
}
const map = {C() : 0};
以下程式碼會產生此診斷,因為常數 Map 包含類型為 C
的索引鍵,且類別 C
覆寫了 hashCode
的實作
class C {
const C();
int get hashCode => 3;
}
const map = {C() : 0};
常見修正方式
#如果您可以從類別中移除 ==
和 hashCode
的實作,請執行此操作
class C {
const C();
}
const map = {C() : 0};
如果您無法從類別中移除 ==
和 hashCode
的實作,則將 Map 設為非常數
class C {
const C();
bool operator ==(Object other) => true;
}
final map = {C() : 0};
const_未初始化
#必須初始化常數 '{0}'。
描述
#當宣告為常數的變數沒有初始化運算式時,分析器會產生此診斷。
範例
#以下程式碼會產生此診斷,因為 c
未初始化
const c;
常見修正方式
#新增初始化運算式
const c = 'c';
const_set_元素不是基本相等性
#const_set_element_type_implements_equals
)
常數 Set 中的元素無法覆寫 '==' 運算子或 'hashCode',但類型 '{0}' 卻覆寫了。
描述
#當用作常數 Set 實值中的元素物件類別實作 ==
運算子、 getter hashCode
或兩者時,分析器會產生此診斷。常數 Set 的實作同時使用 ==
運算子和 hashCode
getter,因此除了從 Object
繼承的實作之外的任何實作,都需要在編譯時期執行任意程式碼,而這是 UnimplementedError。
範例
#以下程式碼會產生此診斷,因為常數 Set 包含類型為 C
的元素,且類別 C
覆寫了 ==
的實作
class C {
const C();
bool operator ==(Object other) => true;
}
const set = {C()};
以下程式碼會產生此診斷,因為常數 Set 包含類型為 C
的元素,且類別 C
覆寫了 hashCode
的實作
class C {
const C();
int get hashCode => 3;
}
const map = {C()};
常見修正方式
#如果您可以從類別中移除 ==
和 hashCode
的實作,請執行此操作
class C {
const C();
}
const set = {C()};
如果您無法從類別中移除 ==
和 hashCode
的實作,則將 Set 設為非常數
class C {
const C();
bool operator ==(Object other) => true;
}
final set = {C()};
const_spread預期是清單或_set
#在此展開中,預期應為 List 或 Set。
描述
#當常數 List 或 Set 中展開運算子的運算式評估為 List 或 Set 以外的項目時,分析器會產生此診斷。
範例
#以下程式碼會產生此診斷,因為 list1
的值為 null
,既不是 List 也不是 Set
const dynamic list1 = 42;
const List<int> list2 = [...list1];
常見修正方式
#將運算式變更為評估為常數 List 或常數 Set 的項目
const dynamic list1 = [42];
const List<int> list2 = [...list1];
const_spread預期是_map
#在此展開中,預期應為 Map。
描述
#當常數 Map 中展開運算子的運算式評估為 Map 以外的項目時,分析器會產生此診斷。
範例
#以下程式碼會產生此診斷,因為 map1
的值為 null
,不是 Map
const dynamic map1 = 42;
const Map<String, int> map2 = {...map1};
常見修正方式
#將運算式變更為評估為常數 Map 的項目
const dynamic map1 = {'answer': 42};
const Map<String, int> map2 = {...map1};
const_搭配非_const
#正在呼叫的建構函式不是 const 建構函式。
描述
#當關鍵字 const
用於叫用未標記為 const
的建構函式時,分析器會產生此診斷。
範例
#以下程式碼會產生此診斷,因為 A
中的建構函式不是 const 建構函式
class A {
A();
}
A f() => const A();
常見修正方式
#如果想要且有可能使類別成為常數類別(方法是使類別的所有欄位,包括繼承的欄位,都成為 final),則將關鍵字 const
新增至建構函式
class A {
const A();
}
A f() => const A();
否則,移除關鍵字 const
class A {
A();
}
A f() => A();
const_搭配非常數引數
#常數建立的引數必須是常數運算式。
描述
#當使用非常數運算式的引數叫用 const 建構函式時,分析器會產生此診斷。
範例
#以下程式碼會產生此診斷,因為 i
不是常數
class C {
final int i;
const C(this.i);
}
C f(int i) => const C(i);
常見修正方式
#將所有引數設為常數運算式,或移除 const
關鍵字以使用建構函式的非常數形式
class C {
final int i;
const C(this.i);
}
C f(int i) => C(i);
具有類型參數的_const
#常數建構函式 tear-off 無法使用類型參數作為類型引數。
常數建立無法使用類型參數作為類型引數。
常數函式 tear-off 無法使用類型參數作為類型引數。
描述
#當類型參數在建構函式的 const
叫用中用作類型引數時,分析器會產生此診斷。不允許這樣做,因為類型參數的值(執行階段將使用的實際類型)在編譯時期無法得知。
範例
#以下程式碼會產生此診斷,因為建立常數時,類型參數 T
正用作類型引數
class C<T> {
const C();
}
C<T> newC<T>() => const C<T>();
常見修正方式
#如果將用於類型參數的類型可以在編譯時期得知,則移除類型參數的使用
class C<T> {
const C();
}
C<int> newC() => const C<int>();
如果將用於類型參數的類型在執行階段之前無法得知,則移除關鍵字 const
class C<T> {
const C();
}
C<T> newC<T>() => C<T>();
continue_標籤無效
#continue_label_on_switch
)
'continue' 陳述式中使用的標籤必須在迴圈或 switch 成員上定義。
描述
#當 continue
陳述式中的標籤解析為 switch
陳述式上的標籤時,分析器會產生此診斷。
範例
#以下程式碼會產生此診斷,因為用於標記 switch
陳述式的標籤 l
用於 continue
陳述式中
void f(int i) {
l: switch (i) {
case 0:
continue l;
}
}
常見修正方式
#尋找達成您所需的控制流程的不同方法;例如,透過引入重新執行 switch
陳述式的迴圈。
struct或_union的建立
#'Struct' 和 'Union' 的子類別由原生記憶體支援,無法由產生器建構函式具現化。
描述
#當使用產生器建構函式具現化 Struct
或 Union
的子類別時,分析器會產生此診斷。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼會產生此診斷,因為類別 C
是使用產生器建構函式具現化的
import 'dart:ffi';
final class C extends Struct {
@Int32()
external int a;
}
void f() {
C();
}
常見修正方式
#如果您需要配置類別描述的結構,則使用 ffi
套件來執行此操作
import 'dart:ffi';
import 'package:ffi/ffi.dart';
final class C extends Struct {
@Int32()
external int a;
}
void f() {
final pointer = calloc.allocate<C>(4);
final c = pointer.ref;
print(c);
calloc.free(pointer);
}
使用非類型建立
#名稱 '{0}' 不是類別。
描述
#當使用 new
或 const
的實例建立指定未定義為類別的名稱時,分析器會產生此診斷。
範例
#以下程式碼會產生此診斷,因為 f
是函式而不是類別
int f() => 0;
void g() {
new f();
}
常見修正方式
#如果應建立類別,則將無效名稱替換為有效類別的名稱
int f() => 0;
void g() {
new Object();
}
如果名稱是函式的名稱,且您想要叫用該函式,則移除 new
或 const
關鍵字
int f() => 0;
void g() {
f();
}
無效程式碼
#無效程式碼。
無效程式碼:已指派給萬用字元變數已標記為 late 且永遠無法參考,因此永遠不會評估此初始化運算式。
描述
#當找到不會執行的程式碼時,分析器會產生此診斷,因為執行永遠不會到達該程式碼。
範例
#以下程式碼會產生此診斷,因為 print
的叫用發生在函式傳回之後
void f() {
return;
print('here');
}
常見修正方式
#如果不需要程式碼,則移除它
void f() {
return;
}
如果需要執行程式碼,則將程式碼移至將會執行的位置
void f() {
print('here');
return;
}
或者,重新撰寫之前的程式碼,使其可以到達
void f({bool skipPrinting = true}) {
if (skipPrinting) {
return;
}
print('here');
}
無效程式碼_catch後面的_catch
#無效程式碼:在 'catch (e)' 或 'on Object catch (e)' 之後的 Catch 子句永遠不會到達。
描述
#當找到無法執行的 catch
子句時,分析器會產生此診斷,因為它在 catch (e)
或 on Object catch (e)
形式的 catch
子句之後。將選取與擲回物件相符的第一個 catch
子句,而這兩種形式都會與任何物件相符,因此不會選取它們之後的任何 catch
子句。
範例
#下列程式碼會產生此診斷訊息
void f() {
try {
} catch (e) {
} on String {
}
}
常見修正方式
#如果子句應該是可選取的,則將子句移至一般子句之前
void f() {
try {
} on String {
} catch (e) {
}
}
如果子句不需要是可選取的,則移除它
void f() {
try {
} catch (e) {
}
}
無效程式碼_on_catch_子類型
#無效程式碼:此 on-catch 區塊將不會執行,因為 '{0}' 是 '{1}' 的子類型,因此已在先前捕捉到。
描述
#當找到無法執行的 catch
子句時,分析器會產生此診斷,因為它在捕捉相同類型或子句類型之父類型的 catch
子句之後。將選取與擲回物件相符的第一個 catch
子句,而先前的子句永遠與醒目提示子句可比對的任何項目相符,因此永遠不會選取醒目提示的子句。
範例
#下列程式碼會產生此診斷訊息
void f() {
try {
} on num {
} on int {
}
}
常見修正方式
#如果子句應該是可選取的,則將子句移至一般子句之前
void f() {
try {
} on int {
} on num {
}
}
如果子句不需要是可選取的,則移除它
void f() {
try {
} on num {
}
}
無效_null_感知_運算式
#左運算元不可為 null,因此永遠不會執行右運算元。
描述
#分析器在兩種情況下會產生此診斷。
第一種情況是當 ??
運算子的左運算元不可為 null
時。只有在左運算元的值為 null
時,才會評估右運算元,而且因為左運算元不可為 null
,因此永遠不會評估右運算元。
第二種情況是當使用 ??=
運算子的指派左側不可為 null
時。只有在左側的值為 null
時,才會評估右側,而且因為左側不可為 null
,因此永遠不會評估右側。
範例
#以下程式碼會產生此診斷,因為 x
不可為 null
int f(int x) {
return x ?? 0;
}
以下程式碼會產生此診斷,因為 f
不可為 null
class C {
int f = -1;
void m(int x) {
f ??= x;
}
}
常見修正方式
#如果針對 ??
運算子報告診斷,則移除 ??
運算子和右運算元
int f(int x) {
return x;
}
如果針對指派報告診斷,且不需要指派,則移除指派
class C {
int f = -1;
void m(int x) {
}
}
如果需要指派,但應根據不同的條件,則重新撰寫程式碼以使用 =
和不同的條件
class C {
int f = -1;
void m(int x) {
if (f < 0) {
f = x;
}
}
}
預設清單建構子
#當啟用 Null 安全性時,預設的 'List' 建構函式無法使用。
描述
#當分析器在已選擇加入 Null 安全性的程式碼中找到類別 List
的預設建構函式的使用時,會產生此診斷。
範例
#假設以下程式碼已選擇加入 Null 安全性,它會產生此診斷,因為它使用預設的 List
建構函式
var l = List<int>();
常見修正方式
#如果未提供初始大小,則轉換程式碼以使用 List 實值
var l = <int>[];
如果需要提供初始大小,且元素的單一合理初始值,則使用 List.filled
var l = List.filled(3, 0);
如果需要提供初始大小,但每個元素都需要計算,則使用 List.generate
var l = List.generate(3, (i) => i);
函式類型中的預設值
#函式類型中的參數不能有預設值。
描述
#當與參數相關聯的函式類型包含具有預設值的選用參數時,分析器會產生此診斷。不允許這樣做,因為參數的預設值不是函式類型的一部分,因此包含它們不會提供任何值。
範例
#以下程式碼會產生此診斷,因為參數 p
具有預設值,即使它是參數 g
類型的一部分
void f(void Function([int p = 0]) g) {
}
常見修正方式
#從函式類型的參數中移除預設值
void f(void Function([int p]) g) {
}
重新導向_factory_建構子中的預設值
#重新導向至另一個建構函式的 Factory 建構函式中不允許預設值。
描述
#當重新導向至另一個建構函式的 Factory 建構函式為選用參數指定預設值時,分析器會產生此診斷。
範例
#以下程式碼會產生此診斷,因為 A
中的 Factory 建構函式具有選用參數 x
的預設值
class A {
factory A([int x = 0]) = B;
}
class B implements A {
B([int x = 1]) {}
}
常見修正方式
#從 Factory 建構函式中移除預設值
class A {
factory A([int x]) = B;
}
class B implements A {
B([int x = 1]) {}
}
請注意,此修正可能會變更省略選用參數時使用的值。如果發生這種情況,而且該變更是問題,則考慮使選用參數成為 Factory 方法中的必要參數
class A {
factory A(int x) = B;
}
class B implements A {
B([int x = 1]) {}
}
必要參數的預設值
#必要的具名參數不能有預設值。
描述
#當具名參數同時具有 required
修飾詞和預設值時,分析器會產生此診斷。如果參數是必要的,則在呼叫站點始終會提供參數的值,因此永遠不會使用預設值。
範例
#以下程式碼會產生此診斷
void log({required String message = 'no message'}) {}
常見修正方式
#如果參數確實是必要的,則移除預設值
void log({required String message}) {}
如果參數並非始終必要,則移除 required
修飾詞
void log({String message = 'no message'}) {}
擴充功能的延遲載入匯入
#延遲程式庫的匯入必須隱藏所有擴充功能。
描述
#當使用延遲匯入匯入的程式庫宣告在匯入程式庫中可見的擴充功能時,分析器會產生此診斷。擴充功能方法會在編譯時期解析,而延遲程式庫中的擴充功能在編譯時期無法使用。
有關更多資訊,請查看 延遲載入程式庫。
範例
#假設檔案 a.dart
定義具名擴充功能
class C {}
extension E on String {
int get size => length;
}
以下程式碼會產生此診斷,因為具名擴充功能對程式庫可見
import 'a.dart' deferred as a;
void f() {
a.C();
}
常見修正方式
#如果程式庫必須匯入為 deferred
,則新增 show
子句列出正在參考的名稱,或新增 hide
子句列出所有具名擴充功能。新增 show
子句看起來會像這樣
import 'a.dart' deferred as a show C;
void f() {
a.C();
}
新增 hide
子句看起來會像這樣
import 'a.dart' deferred as a hide E;
void f() {
a.C();
}
使用第一個修正的好處是,如果將新擴充功能新增至匯入的程式庫,則擴充功能不會導致產生診斷。
如果程式庫不需要匯入為 deferred
,或者如果您需要使用其中宣告的擴充功能方法,則移除關鍵字 deferred
import 'a.dart' as a;
void f() {
a.C();
}
明確未賦值的_late_區域變數
#在此點,late 區域變數 '{0}' 明確未指派。
描述
#當 明確指派 分析顯示標記為 late
的區域變數在指派之前讀取時,分析器會產生此診斷。
範例
#以下程式碼會產生此診斷,因為 x
在讀取之前未指派值
void f(bool b) {
late int x;
print(x);
}
常見修正方式
#在從變數讀取之前,將值指派給變數
void f(bool b) {
late int x;
x = b ? 1 : 0;
print(x);
}
相依性欄位不是_map
#欄位 '{0}' 的值應為 Map。
描述
#當 dependencies
或 dev_dependencies
索引鍵的值不是 Map 時,分析器會產生此診斷。
範例
#以下程式碼會產生此診斷,因為最上層 dependencies
索引鍵的值是 List
name: example
dependencies:
- meta
常見修正方式
#使用 Map 作為 dependencies
索引鍵的值
name: example
dependencies:
meta: ^1.0.2
已淘汰的冒號作為預設值
#在預設值之前使用冒號作為分隔符號已過時,且在語言版本 3.0 及更高版本中將不再支援。
描述
#當冒號 (:
) 用作選用具名參數的預設值之前的分隔符號時,分析器會產生此診斷。雖然允許使用此語法,但建議改用等號 (=
)。
範例
#以下程式碼會產生此診斷,因為在選用參數 i
的預設值之前使用了冒號
void f({int i : 0}) {}
常見修正方式
#將冒號替換為等號。
void f({int i = 0}) {}
已淘汰的匯出使用
#間接匯入 '{0}' 的能力已過時。
描述
#當一個程式庫從第二個程式庫匯入名稱,且第二個程式庫從第三個程式庫匯出名稱,但已指出未來不會匯出第三個程式庫時,分析器會產生此診斷。
範例
#假設程式庫 a.dart
定義類別 A
class A {}
以及第二個程式庫 b.dart
匯出 a.dart
,但已將匯出標記為已過時
import 'a.dart';
@deprecated
export 'a.dart';
以下程式碼會產生此診斷,因為類別 A
在未來的某些版本中不會從 b.dart
匯出
import 'b.dart';
A? a;
常見修正方式
#如果名稱可從您可以匯入的不同程式庫取得,則將現有的匯入替換為該程式庫的匯入(如果您仍然需要舊的匯入,則新增定義程式庫的匯入)
import 'a.dart';
A? a;
如果名稱不可用,則尋找程式庫作者的指示或直接聯絡他們,以瞭解如何更新您的程式碼。
已淘汰的欄位
#欄位 '{0}' 已不再使用,可以移除。
描述
#當在 pubspec.yaml
檔案中使用已過時的索引鍵時,分析器會產生此診斷。未使用的索引鍵會佔用空間,且可能暗示不再有效的語意。
範例
#以下程式碼會產生此診斷,因為 author
索引鍵已不再使用
name: example
author: 'Dash'
常見修正方式
#移除已過時的索引鍵
name: example
已淘汰的成員使用
#'{0}' 已過時,不應使用。
'{0}' 已過時,不應使用。{1}
描述
#當已過時的程式庫或類別成員在不同的套件中使用時,分析器會產生此診斷。
範例
#如果類別 C
中的方法 m
以 @deprecated
註解,則以下程式碼會產生此診斷
void f(C c) {
c.m();
}
常見修正方式
#使用 @deprecated
註解之宣告的文件應指出要使用哪些程式碼來取代已過時的程式碼。
來自相同套件的已淘汰成員使用
#'{0}' 已過時,不應使用。
'{0}' 已過時,不應使用。{1}
描述
#當已過時的程式庫成員或類別成員在宣告它的同一個套件中使用時,分析器會產生此診斷。
範例
#以下程式碼會產生此診斷,因為 x
已過時
@deprecated
var x = 0;
var y = x;
常見修正方式
#修正取決於已過時的內容以及取代項目。已過時宣告的文件應指出要使用哪些程式碼來取代已過時的程式碼。
註解參考中已淘汰的_new
#在註解參考中使用 'new' 關鍵字已過時。
描述
#當註解參考(文件註解中以方括號括住的宣告名稱)使用關鍵字 new
來參考建構函式時,分析器會產生此診斷。此形式已過時。
範例
#以下程式碼會產生此診斷,因為未命名的建構函式正使用 new C
參考
/// See [new C].
class C {
C();
}
以下程式碼會產生此診斷,因為具名建構函式 c
正使用 new C.c
參考
/// See [new C.c].
class C {
C.c();
}
常見修正方式
#如果您要參考具名建構函式,則移除關鍵字 new
/// See [C.c].
class C {
C.c();
}
如果您要參考未命名的建構函式,則移除關鍵字 new
,並在類別名稱後附加 .new
/// See [C.new].
class C {
C.c();
}
函式已淘汰的子類型
#擴充 'Function' 已過時。
實作 'Function' 無效。
混入 'Function' 已過時。
描述
#當類別 Function
用於類別或 Mixin 的 extends
、implements
或 with
子句中時,分析器會產生此診斷。以這種方式使用類別 Function
沒有語意值,因此實際上是無效程式碼。
範例
#以下程式碼會產生此診斷,因為 Function
用作 F
的父類別
class F extends Function {}
常見修正方式
#從它所在的任何子句中移除類別 Function
,如果 Function
是子句中唯一的類型,則移除整個子句
class F {}
不允許的類型具現化運算式
#只有泛型類型、泛型函式、泛型實例方法或泛型建構函式可以有類型引數。
描述
#當具有任何非允許值種類之一的值的運算式後接類型引數時,分析器會產生此診斷。允許的值種類為
- 泛型類型,
- 泛型建構函式,以及
- 泛型函式,包括最上層函式、靜態和實例成員以及區域函式。
範例
#以下程式碼會產生此診斷,因為 i
是最上層變數,不是允許的情況之一
int i = 1;
void f() {
print(i<int>);
}
常見修正方式
#如果參考的值正確,則移除類型引數
int i = 1;
void f() {
print(i);
}
除法最佳化
#運算子 x ~/ y 比 (x / y).toInt() 更有效率。
描述
#當除以兩個數字的結果使用 toInt
轉換為整數時,分析器會產生此診斷。Dart 具有內建的整數除法運算子,既更有效率又更簡潔。
範例
#以下程式碼會產生此診斷,因為除以 x
和 y
的結果使用 toInt
轉換為整數
int divide(int x, int y) => (x / y).toInt();
常見修正方式
#使用整數除法運算子 (~/
)
int divide(int x, int y) => x ~/ y;
重複的建構子
#已定義名稱為 '{0}' 的建構函式。
已定義未命名的建構函式。
描述
#當類別宣告多個未命名的建構函式,或宣告多個具有相同名稱的建構函式時,分析器會產生此診斷。
範例
#以下程式碼會產生此診斷,因為未命名的建構函式有兩個宣告
class C {
C();
C();
}
以下程式碼會產生此診斷,因為名稱為 m
的建構函式有兩個宣告
class C {
C.m();
C.m();
}
常見修正方式
#如果有多個未命名的建構函式,且需要所有建構函式,則為它們全部或除其中一個之外的所有建構函式命名
class C {
C();
C.n();
}
如果有多個未命名的建構函式,且除了其中一個之外的所有建構函式都是不需要的,則移除不需要的建構函式
class C {
C();
}
如果有多個具名建構式,且所有建構式都是必要的,則重新命名除了其中一個以外的所有建構式
class C {
C.m();
C.n();
}
如果有多個具名建構式,且除了其中一個以外的所有建構式都是不必要的,則移除不必要的建構式
class C {
C.m();
}
重複的定義
#名稱「{0}」已定義。
描述
#當宣告名稱時,且在相同範圍中存在先前宣告的同名名稱時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為名稱 x
被宣告了兩次
int x = 0;
int x = 1;
常見修正方式
#為其中一個宣告選擇不同的名稱。
int x = 0;
int y = 1;
重複的匯出
#重複匯出。
描述
#當找到與檔案中先前的匯出指令相同的匯出指令時,分析器會產生此診斷訊息。第二個匯出指令沒有增加任何價值,應該移除。
範例
#以下程式碼會產生此診斷訊息,因為相同的程式庫被匯出了兩次
export 'package:meta/meta.dart';
export 'package:meta/meta.dart';
常見修正方式
#移除不必要的匯出
export 'package:meta/meta.dart';
重複的欄位形式參數
#欄位「{0}」無法在同一個建構式中由多個參數初始化。
描述
#當建構式的參數列表中,同一個欄位有多個初始化形式參數時,分析器會產生此診斷訊息。指派一個會立即被覆寫的值是沒有意義的。
範例
#以下程式碼會產生此診斷訊息,因為 this.f
在參數列表中出現了兩次
class C {
int f;
C(this.f, this.f) {}
}
常見修正方式
#移除其中一個初始化形式參數
class C {
int f;
C(this.f) {}
}
重複的欄位名稱
#欄位名稱「{0}」已在此記錄中使用。
描述
#當記錄字面量或記錄類型註釋包含一個欄位,其名稱與同一個字面量或類型中先前宣告的欄位名稱相同時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為記錄字面量有兩個名為 a
的欄位
var r = (a: 1, a: 2);
以下程式碼會產生此診斷訊息,因為記錄類型註釋有兩個名為 a
的欄位,一個是位置欄位,另一個是具名欄位
void f((int a, {int a}) r) {}
常見修正方式
#重新命名其中一個或兩個欄位
var r = (a: 1, b: 2);
重複的隱藏名稱
#重複隱藏名稱。
描述
#當一個名稱在 hide
子句中多次出現時,分析器會產生此診斷訊息。重複名稱是不必要的。
範例
#以下程式碼會產生此診斷訊息,因為名稱 min
被隱藏了不只一次
import 'dart:math' hide min, min;
var x = pi;
常見修正方式
#如果名稱在一個或多個地方被錯誤輸入,則更正錯誤輸入的名稱
import 'dart:math' hide max, min;
var x = pi;
如果名稱沒有被錯誤輸入,則從列表中移除不必要的名稱
import 'dart:math' hide min;
var x = pi;
重複的_ignore
#診斷訊息「{0}」在此處不需要被忽略,因為它已經被忽略了。
描述
#當診斷訊息名稱出現在 ignore
註解中,但該診斷訊息已經被忽略時,分析器會產生此診斷訊息,可能是因為它已經包含在同一個 ignore
註解中,或是因為它出現在 ignore-in-file
註解中。
範例
#以下程式碼會產生此診斷訊息,因為名為 unused_local_variable
的診斷訊息已經被整個檔案忽略,因此不需要在特定行上忽略它
// ignore_for_file: unused_local_variable
void f() {
// ignore: unused_local_variable
var x = 0;
}
以下程式碼會產生此診斷訊息,因為名為 unused_local_variable
的診斷訊息在同一行被忽略了兩次
void f() {
// ignore: unused_local_variable, unused_local_variable
var x = 0;
}
常見修正方式
#移除忽略註解,或者如果忽略註解忽略了多個診斷訊息,則移除不必要的診斷訊息名稱
// ignore_for_file: unused_local_variable
void f() {
var x = 0;
}
重複的匯入
#重複匯入。
描述
#當找到與檔案中先前的匯入指令相同的匯入指令時,分析器會產生此診斷訊息。第二個匯入指令沒有增加任何價值,應該移除。
範例
#下列程式碼會產生此診斷訊息
import 'package:meta/meta.dart';
import 'package:meta/meta.dart';
@sealed class C {}
常見修正方式
#移除不必要的匯入
import 'package:meta/meta.dart';
@sealed class C {}
重複的具名引數
#具名參數「{0}」的引數已經指定過了。
描述
#當調用具有兩個或多個同名具名引數時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為有兩個名稱為 a
的引數
void f(C c) {
c.m(a: 0, a: 1);
}
class C {
void m({int? a, int? b}) {}
}
常見修正方式
#如果其中一個引數應該有不同的名稱,則更改名稱
void f(C c) {
c.m(a: 0, b: 1);
}
class C {
void m({int? a, int? b}) {}
}
如果其中一個引數是錯誤的,則移除它
void f(C c) {
c.m(a: 1);
}
class C {
void m({int? a, int? b}) {}
}
重複的_part
#程式庫已經包含一個 URI 為「{0}」的部分。
描述
#當單一檔案在多個 part 指令中被引用時,分析器會產生此診斷訊息。
範例
#給定一個包含以下內容的檔案 part.dart
part of 'test.dart';
以下程式碼會產生此診斷訊息,因為檔案 part.dart
被包含了多次
part 'part.dart';
part 'part.dart';
常見修正方式
#移除除了第一個以外的所有重複 part 指令
part 'part.dart';
模式賦值變數重複
#變數「{0}」已在此模式中被賦值。
描述
#當單一模式變數在同一個模式賦值中被賦值多次時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為變數 a
在模式 (a, a)
中被賦值了兩次
int f((int, int) r) {
int a;
(a, a) = r;
return a;
}
常見修正方式
#如果您需要捕獲所有值,則為每個要匹配的子模式使用唯一的變數
int f((int, int) r) {
int a, b;
(a, b) = r;
return a + b;
}
如果某些值不需要被捕獲,則使用萬用字元模式 _
以避免必須將值綁定到變數
int f((int, int) r) {
int a;
(_, a) = r;
return a;
}
模式欄位重複
#欄位「{0}」已在此模式中被匹配。
描述
#當記錄模式多次匹配同一個欄位,或者當物件模式多次匹配同一個 getter 時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為記錄欄位 a
在同一個記錄模式中被匹配了兩次
void f(({int a, int b}) r) {
switch (r) {
case (a: 1, a: 2):
return;
}
}
以下程式碼會產生此診斷訊息,因為 getter f
在同一個物件模式中被匹配了兩次
void f(Object o) {
switch (o) {
case C(f: 1, f: 2):
return;
}
}
class C {
int? f;
}
常見修正方式
#如果模式應該匹配重複欄位的多個值,則使用邏輯或模式
void f(({int a, int b}) r) {
switch (r) {
case (a: 1, b: _) || (a: 2, b: _):
break;
}
}
如果模式應該匹配多個欄位,則更改其中一個欄位的名稱
void f(({int a, int b}) r) {
switch (r) {
case (a: 1, b: 2):
return;
}
}
模式中重複的其餘元素
#在列表或 Map 模式中,最多允許一個 rest 元素。
描述
#當列表或 Map 模式中存在多個 rest 模式時,分析器會產生此診斷訊息。rest 模式將捕獲任何未被其他子模式匹配的值,這使得後續的 rest 模式變得不必要,因為沒有剩餘任何東西可以捕獲。
範例
#以下程式碼會產生此診斷訊息,因為列表模式中有兩個 rest 模式
void f(List<int> x) {
if (x case [0, ..., ...]) {}
}
常見修正方式
#移除除了其中一個以外的所有 rest 模式
void f(List<int> x) {
if (x case [0, ...]) {}
}
重複的顯示名稱
#重複顯示名稱。
描述
#當一個名稱在 show
子句中多次出現時,分析器會產生此診斷訊息。重複名稱是不必要的。
範例
#以下程式碼會產生此診斷訊息,因為名稱 min
被顯示了不只一次
import 'dart:math' show min, min;
var x = min(2, min(0, 1));
常見修正方式
#如果名稱在一個或多個地方被錯誤輸入,則更正錯誤輸入的名稱
import 'dart:math' show max, min;
var x = max(2, min(0, 1));
如果名稱沒有被錯誤輸入,則從列表中移除不必要的名稱
import 'dart:math' show min;
var x = min(2, min(0, 1));
重複的變數模式
#變數「{0}」已在此模式中定義。
描述
#當邏輯 AND 模式的分支宣告了一個變數,該變數已在同一個模式的較早分支中宣告時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為變數 a
在邏輯 AND 模式的兩個分支中都被宣告了
void f((int, int) r) {
if (r case (var a, 0) && (0, var a)) {
print(a);
}
}
常見修正方式
#如果您需要在多個分支中捕獲匹配的值,則更改變數的名稱,使其成為唯一的
void f((int, int) r) {
if (r case (var a, 0) && (0, var b)) {
print(a + b);
}
}
如果您只需要在一個分支上捕獲匹配的值,則從除了其中一個分支以外的所有分支中移除變數模式
void f((int, int) r) {
if (r case (var a, 0) && (0, _)) {
print(a);
}
}
空的_map_模式
#Map 模式必須至少有一個條目。
描述
#當 Map 模式為空時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 Map 模式為空
void f(Map<int, String> x) {
if (x case {}) {}
}
常見修正方式
#如果模式應該匹配任何 Map,則將其替換為物件模式
void f(Map<int, String> x) {
if (x case Map()) {}
}
如果模式應該僅匹配空 Map,則檢查模式中的長度
void f(Map<int, String> x) {
if (x case Map(isEmpty: true)) {}
}
具有逗號的空記錄字面值
#沒有欄位的記錄字面量不能有尾隨逗號。
描述
#當沒有欄位的記錄字面量具有尾隨逗號時,分析器會產生此診斷訊息。空的記錄字面量不能包含逗號。
範例
#以下程式碼會產生此診斷訊息,因為空的記錄字面量具有尾隨逗號
var r = (,);
常見修正方式
#如果記錄旨在為空,則移除逗號
var r = ();
如果記錄旨在具有一個或多個欄位,則新增用於計算這些欄位值的表達式
var r = (3, 4);
空的記錄類型具名欄位清單
#記錄類型中具名欄位的列表不能為空。
描述
#當記錄類型具有空的具名欄位列表時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為記錄類型具有空的具名欄位列表
void f((int, int, {}) r) {}
常見修正方式
#如果記錄旨在具有具名欄位,則新增欄位的類型和名稱
void f((int, int, {int z}) r) {}
如果記錄不旨在具有具名欄位,則移除大括號
void f((int, int) r) {}
具有逗號的空記錄類型
#沒有欄位的記錄類型不能有尾隨逗號。
描述
#當沒有欄位的記錄類型具有尾隨逗號時,分析器會產生此診斷訊息。空的記錄類型不能包含逗號。
範例
#以下程式碼會產生此診斷訊息,因為空的記錄類型具有尾隨逗號
void f((,) r) {}
常見修正方式
#如果記錄類型旨在為空,則移除逗號
void f(() r) {}
如果記錄類型旨在具有一個或多個欄位,則新增這些欄位的類型
void f((int, int) r) {}
空的_struct
#類別「{0}」不能為空,因為它是「{1}」的子類別。
描述
#當 Struct
或 Union
的子類別沒有任何欄位時,分析器會產生此診斷訊息。不支援空的 Struct
或 Union
。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼會產生此診斷訊息,因為擴展 Struct
的類別 C
沒有宣告任何欄位
import 'dart:ffi';
final class C extends Struct {}
常見修正方式
#如果類別旨在作為結構體,則宣告一個或多個欄位
import 'dart:ffi';
final class C extends Struct {
@Int32()
external int x;
}
如果類別旨在用作 Pointer
的類型引數,則使其成為 Opaque
的子類別
import 'dart:ffi';
final class C extends Opaque {}
如果類別不旨在作為結構體,則移除或更改 extends 子句
class C {}
列舉常數與封閉項名稱相同
#列舉值的名稱不能與列舉的名稱相同。
描述
#當列舉值與宣告它的列舉具有相同的名稱時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為列舉值 E
與封閉列舉 E
具有相同的名稱
enum E {
E
}
常見修正方式
#如果列舉的名稱是正確的,則重新命名常數
enum E {
e
}
如果常數的名稱是正確的,則重新命名列舉
enum F {
E
}
具有非常數建構子的列舉常數
#調用的建構式不是「const」建構式。
描述
#當使用工廠建構式或未標記為 const
的產生器建構式建立列舉值時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為列舉值 e
正在由工廠建構式初始化
enum E {
e();
factory E() => e;
}
常見修正方式
#使用標記為 const
的產生器建構式
enum E {
e._();
factory E() => e;
const E._();
}
具有實例變數的列舉混入
#應用於列舉的 Mixin 不能具有實例變數。
描述
#當應用於列舉的 Mixin 宣告了一個或多個實例變數時,分析器會產生此診斷訊息。這是不允許的,因為列舉值是常數,並且列舉中的建構式無法初始化任何 Mixin 的欄位。
範例
#以下程式碼會產生此診斷訊息,因為 Mixin M
定義了實例欄位 x
mixin M {
int x = 0;
}
enum E with M {
a
}
常見修正方式
#如果您需要應用 Mixin,則將所有實例欄位更改為 getter 和 setter 對,並在必要時在列舉中實現它們
mixin M {
int get x => 0;
}
enum E with M {
a
}
如果您不需要應用 Mixin,則移除它
enum E {
a
}
具有抽象成員的列舉
#「{0}」必須具有方法主體,因為「{1}」是一個列舉。
描述
#當找到列舉的成員沒有具體實現時,分析器會產生此診斷訊息。列舉不允許包含抽象成員。
範例
#以下程式碼會產生此診斷訊息,因為 m
是一個抽象方法,而 E
是一個列舉
enum E {
e;
void m();
}
常見修正方式
#為成員提供一個實現
enum E {
e;
void m() {}
}
具有名稱值的列舉
#名稱 'values' 不是列舉的有效名稱。
描述
#當列舉被宣告為具有名稱 values
時,分析器會產生此診斷訊息。這是不允許的,因為列舉具有隱含的靜態欄位,名為 values
,而兩者會衝突。
範例
#以下程式碼會產生此診斷訊息,因為有一個列舉宣告具有名稱 values
enum values {
c
}
常見修正方式
#將列舉重新命名為 values
以外的名稱。
const_set中相等的元素
#常數 Set 字面量中的兩個元素不能相等。
描述
#當常數 Set 字面量中的兩個元素具有相同的值時,分析器會產生此診斷訊息。Set 只能包含每個值一次,這表示其中一個值是不必要的。
範例
#以下程式碼會產生此診斷訊息,因為字串 'a'
被指定了兩次
const Set<String> set = {'a', 'a'};
常見修正方式
#移除其中一個重複的值
const Set<String> set = {'a'};
請注意,字面量 Set 保留其元素的順序,因此選擇移除哪個元素可能會影響迭代器返回元素的順序。
set中相等的元素
#Set 字面量中的兩個元素不應該相等。
描述
#當非常數 Set 中的元素與同一個 Set 中的先前元素相同時,分析器會產生此診斷訊息。如果兩個元素相同,則第二個值會被忽略,這使得同時擁有這兩個元素變得毫無意義,並且可能表示一個錯誤。
範例
#以下程式碼會產生此診斷訊息,因為元素 1
出現了兩次
const a = 1;
const b = 1;
var s = <int>{a, b};
常見修正方式
#如果兩個元素都應該包含在 Set 中,則更改其中一個元素
const a = 1;
const b = 2;
var s = <int>{a, b};
如果只需要其中一個元素,則移除不需要的那個
const a = 1;
var s = <int>{a};
請注意,字面量 Set 保留其元素的順序,因此選擇移除哪個元素可能會影響迭代器返回元素的順序。
const_map中相等的金鑰
#常數 Map 字面量中的兩個鍵不能相等。
描述
#當常數 Map 中的鍵與同一個 Map 中的先前鍵相同時,分析器會產生此診斷訊息。如果兩個鍵相同,則第二個值會覆寫第一個值,這使得同時擁有這兩個鍵值對變得毫無意義。
範例
#以下程式碼會產生此診斷訊息,因為鍵 1
被使用了兩次
const map = <int, String>{1: 'a', 2: 'b', 1: 'c', 4: 'd'};
常見修正方式
#如果兩個條目都應該包含在 Map 中,則更改其中一個鍵使其不同
const map = <int, String>{1: 'a', 2: 'b', 3: 'c', 4: 'd'};
如果只需要其中一個條目,則移除不需要的那個
const map = <int, String>{1: 'a', 2: 'b', 4: 'd'};
請注意,字面量 Map 保留其條目的順序,因此選擇移除哪個條目可能會影響迭代器返回鍵和值的順序。
map中相等的金鑰
#Map 字面量中的兩個鍵不應該相等。
描述
#當非常數 Map 中的鍵與同一個 Map 中的先前鍵相同時,分析器會產生此診斷訊息。如果兩個鍵相同,則第二個值會覆寫第一個值,這使得同時擁有這兩個鍵值對變得毫無意義,並且可能表示一個錯誤。
範例
#以下程式碼會產生此診斷訊息,因為鍵 a
和 b
具有相同的值
const a = 1;
const b = 1;
var m = <int, String>{a: 'a', b: 'b'};
常見修正方式
#如果兩個條目都應該包含在 Map 中,則更改其中一個鍵
const a = 1;
const b = 2;
var m = <int, String>{a: 'a', b: 'b'};
如果只需要其中一個條目,則移除不需要的那個
const a = 1;
var m = <int, String>{a: 'a'};
請注意,字面量 Map 保留其條目的順序,因此選擇移除哪個條目可能會影響迭代器返回鍵和值的順序。
map_模式中相等的金鑰
#Map 模式中的兩個鍵不能相等。
描述
#當 Map 模式包含多個具有相同名稱的鍵時,分析器會產生此診斷訊息。同一個鍵不能被匹配兩次。
範例
#以下程式碼會產生此診斷訊息,因為鍵 'a'
出現了兩次
void f(Map<String, int> x) {
if (x case {'a': 1, 'a': 2}) {}
}
常見修正方式
#如果您嘗試匹配兩個不同的鍵,則更改模式中的其中一個鍵
void f(Map<String, int> x) {
if (x case {'a': 1, 'b': 2}) {}
}
如果您嘗試匹配同一個鍵,但允許匹配多個模式中的任何一個,則使用邏輯或模式
void f(Map<String, int> x) {
if (x case {'a': 1 || 2}) {}
}
預期一個清單模式類型引數
#列表模式需要一個或零個類型引數,但找到了 {0} 個。
描述
#當列表模式具有多個類型引數時,分析器會產生此診斷訊息。列表模式可以具有零個或一個類型引數,但不能有多個。
範例
#以下程式碼會產生此診斷訊息,因為列表模式 ([0]
) 具有兩個類型引數
void f(Object x) {
if (x case <int, int>[0]) {}
}
常見修正方式
#移除除了其中一個以外的所有類型引數
void f(Object x) {
if (x case <int>[0]) {}
}
預期一個清單類型引數
#列表字面量需要一個或零個類型引數,但找到了 {0} 個。
描述
#當列表字面量具有多個類型引數時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為列表字面量具有兩個類型引數,但它最多只能有一個
var l = <int, int>[];
常見修正方式
#移除除了其中一個以外的所有類型引數
var l = <int>[];
預期一個_set類型引數
#Set 字面量需要一個或零個類型引數,但找到了 {0} 個。
描述
#當 Set 字面量具有多個類型引數時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 Set 字面量具有三個類型引數,但它最多只能有一個
var s = <int, String, int>{0, 'a', 1};
常見修正方式
#移除除了其中一個以外的所有類型引數
var s = <int>{0, 1};
預期兩個_map_模式類型引數
#Map 模式需要兩個或零個類型引數,但找到了 {0} 個。
描述
#當 Map 模式具有一個類型引數或多於兩個類型引數時,分析器會產生此診斷訊息。Map 模式可以具有兩個或零個類型引數,但不能有任何其他數量。
範例
#以下程式碼會產生此診斷訊息,因為 Map 模式 (<int>{}
) 具有一個類型引數
void f(Object x) {
if (x case <int>{0: _}) {}
}
常見修正方式
#新增或移除類型引數,直到有兩個或零個
void f(Object x) {
if (x case <int, int>{0: _}) {}
}
預期兩個_map類型引數
#Map 字面量需要兩個或零個類型引數,但找到了 {0} 個。
描述
#當 Map 字面量具有一個或多於兩個類型引數時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 Map 字面量具有三個類型引數,但它可以有兩個或零個
var m = <int, String, int>{};
常見修正方式
#移除除了兩個以外的所有類型引數
var m = <int, String>{};
匯出內部程式庫
#程式庫「{0}」是內部的,不能被匯出。
描述
#當分析器找到一個匯出指令,其 dart:
URI 引用了內部程式庫時,會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 _interceptors
是一個內部程式庫
export 'dart:_interceptors';
常見修正方式
#移除匯出指令。
匯出舊版符號
#符號「{0}」定義在舊版程式庫中,不能從啟用空值安全性的程式庫中重新匯出。
描述
#當選擇加入空值安全性的程式庫匯出另一個程式庫,而匯出的程式庫選擇退出空值安全性時,分析器會產生此診斷訊息。
範例
#給定一個選擇退出空值安全性的程式庫
// @dart = 2.8
String s;
以下程式碼會產生此診斷訊息,因為它正在匯出選擇退出的程式庫中的符號
export 'optedOut.dart';
class C {}
常見修正方式
#如果可以,遷移匯出的程式庫,使其不需要選擇退出
String? s;
如果無法遷移程式庫,則移除匯出
class C {}
如果匯出的程式庫(選擇退出的那個)本身匯出了一個選擇加入的程式庫,那麼您的程式庫間接匯出選擇加入的程式庫中的符號是有效的。您可以通過在程式庫中的匯出指令中新增一個 hide 組合器來隱藏所有在選擇退出的程式庫中宣告的名稱來做到這一點。
匯出非程式庫
#匯出的程式庫「{0}」不能有 part-of 指令。
描述
#當匯出指令引用的是 part 而不是程式庫時,分析器會產生此診斷訊息。
範例
#給定一個包含以下內容的檔案 part.dart
part of lib;
以下程式碼會產生此診斷訊息,因為檔案 part.dart
是一個 part,而只有程式庫可以被匯出
library lib;
export 'part.dart';
常見修正方式
#移除匯出指令,或將 URI 更改為包含 part 的程式庫的 URI。
map中的運算式
#表達式不能在 Map 字面量中使用。
描述
#當分析器在看起來像 Map 字面量的東西中找到表達式,而不是 Map 條目時,分析器會產生此診斷訊息。
範例
#下列程式碼會產生此診斷訊息
var map = <String, int>{'a': 0, 'b': 1, 'c'};
常見修正方式
#如果表達式旨在計算條目中的鍵或值,請通過將表達式替換為鍵或值來修復此問題。例如
var map = <String, int>{'a': 0, 'b': 1, 'c': 2};
擴充非類別
#類別只能擴展其他類別。
描述
#當 extends
子句包含一個被宣告為類別以外的東西的名稱時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 f
被宣告為函數
void f() {}
class C extends f {}
常見修正方式
#如果您希望類別擴展 Object
以外的類別,則將 extends
子句中的名稱替換為該類別的名稱
void f() {}
class C extends B {}
class B {}
如果您希望類別擴展 Object
,則移除 extends
子句
void f() {}
class C {}
擴充功能作為運算式
#擴展「{0}」不能用作表達式。
描述
#當擴展的名稱在表達式中使用,而不是在擴展覆蓋中或限定對擴展的靜態成員的訪問時,分析器會產生此診斷訊息。由於類別定義了一種類型,因此類別的名稱可用於引用表示類別類型的 Type
實例。另一方面,擴展不定義類型,也不能用作類型字面量。
範例
#以下程式碼會產生此診斷訊息,因為 E
是一個擴展
extension E on int {
static String m() => '';
}
var x = E;
常見修正方式
#將擴展的名稱替換為可以被引用的名稱,例如在擴展上定義的靜態成員
extension E on int {
static String m() => '';
}
var x = E.m();
擴充功能衝突的靜態和實例
#擴展不能定義靜態成員「{0}」和具有相同名稱的實例成員。
描述
#當擴展宣告同時包含一個實例成員和一個具有相同名稱的靜態成員時,分析器會產生此診斷訊息。實例成員和靜態成員不能具有相同的名稱,因為不清楚在擴展主體內不限定地使用該名稱時,正在引用哪個成員。
範例
#以下程式碼會產生此診斷訊息,因為名稱 a
被用於兩個不同的成員
extension E on Object {
int get a => 0;
static int a() => 0;
}
常見修正方式
#重新命名或移除其中一個成員
extension E on Object {
int get a => 0;
static int b() => 0;
}
擴充功能宣告抽象成員
#擴展不能宣告抽象成員。
描述
#當在擴展中宣告抽象宣告時,分析器會產生此診斷訊息。擴展只能宣告具體成員。
範例
#以下程式碼會產生此診斷訊息,因為方法 a
沒有主體
extension E on String {
int a();
}
常見修正方式
#為成員提供一個實現或移除它。
擴充功能宣告建構子
#擴展不能宣告建構式。
描述
#當在擴展中找到建構式宣告時,分析器會產生此診斷訊息。定義建構式是無效的,因為擴展不是類別,並且不可能創建擴展的實例。
範例
#以下程式碼會產生此診斷訊息,因為 E
中存在建構式宣告
extension E on String {
E() : super();
}
常見修正方式
#移除建構式或將其替換為靜態方法。
擴充功能宣告實例欄位
#擴展不能宣告實例欄位。
描述
#當在擴展中找到實例欄位宣告時,分析器會產生此診斷訊息。定義實例欄位是無效的,因為擴展只能新增行為,而不能新增狀態。
範例
#以下程式碼會產生此診斷訊息,因為 s
是一個實例欄位
extension E on String {
String s;
}
常見修正方式
#如果可以在不將值儲存在欄位中的情況下計算值,則嘗試使用 getter 或方法
extension E on String {
String get s => '';
void s(String value) => print(s);
}
如果必須儲存值,但對於每個實例都相同,則嘗試使用靜態欄位
extension E on String {
static String s = '';
}
如果每個實例都需要儲存自己的值,則嘗試使用由靜態 Expando 支持的 getter 和 setter 對
extension E on SomeType {
static final _s = Expando<String>();
String get s => _s[this] ?? '';
set s(String value) => _s[this] = value;
}
擴充功能宣告物件成員
#擴展不能宣告與 'Object' 宣告的成員同名的成員。
描述
#當擴展宣告宣告了一個與類別 Object
中宣告的成員同名的成員時,分析器會產生此診斷訊息。這樣的成員永遠無法使用,因為總是先找到 Object
中的成員。
範例
#以下程式碼會產生此診斷訊息,因為 toString
由 Object
定義
extension E on String {
String toString() => this;
}
常見修正方式
#移除成員或重新命名它,使其名稱不與 Object
中的成員衝突
extension E on String {
String displayString() => this;
}
擴充功能覆寫存取靜態成員
#擴展覆蓋不能用於訪問擴展中的靜態成員。
描述
#當擴展覆蓋是靜態成員調用的接收者時,分析器會產生此診斷訊息。與類別中的靜態成員類似,擴展的靜態成員應使用擴展的名稱而不是擴展覆蓋來訪問。
範例
#以下程式碼會產生此診斷訊息,因為 m
是靜態的
extension E on String {
static void m() {}
}
void f() {
E('').m();
}
常見修正方式
#將擴展覆蓋替換為擴展的名稱
extension E on String {
static void m() {}
}
void f() {
E.m();
}
擴充功能覆寫引數不可賦值
#擴展覆蓋「{0}」的引數類型不能賦值給擴展類型「{1}」。
描述
#當擴展覆蓋的引數不能賦值給擴展所擴展的類型時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 3
不是 String
extension E on String {
void method() {}
}
void f() {
E(3).method();
}
常見修正方式
#如果您正在使用正確的擴展,則更新引數以具有正確的類型
extension E on String {
void method() {}
}
void f() {
E(3.toString()).method();
}
如果有另一個對引數類型有效的擴展,則替換擴展的名稱或解包裝引數,以便找到正確的擴展。
沒有存取的擴充功能覆寫
#擴展覆蓋只能用於訪問實例成員。
描述
#當找到一個擴展覆蓋,但它沒有被用於訪問擴展的成員之一時,分析器會產生此診斷訊息。擴展覆蓋語法沒有任何運行時語義;它僅控制在編譯時選擇哪個成員。
範例
#以下程式碼會產生此診斷訊息,因為 E(i)
不是表達式
extension E on int {
int get a => 0;
}
void f(int i) {
print(E(i));
}
常見修正方式
#如果您想調用擴展的成員之一,則新增調用
extension E on int {
int get a => 0;
}
void f(int i) {
print(E(i).a);
}
如果您不想調用成員,則解包裝引數
extension E on int {
int get a => 0;
}
void f(int i) {
print(i);
}
具有串聯的擴充功能覆寫
#擴展覆蓋沒有值,因此它們不能用作級聯表達式的接收者。
描述
#當擴展覆蓋用作級聯表達式的接收者時,分析器會產生此診斷訊息。級聯表達式 e..m
的值是接收者 e
的值,但擴展覆蓋不是表達式,也沒有值。
範例
#以下程式碼會產生此診斷訊息,因為 E(3)
不是表達式
extension E on int {
void m() {}
}
f() {
E(3)..m();
}
常見修正方式
#使用 .
而不是 ..
extension E on int {
void m() {}
}
f() {
E(3).m();
}
如果有多個級聯訪問,您需要為每個訪問複製擴展覆蓋。
具有_super_形式參數的擴充功能類型建構子
#擴展類型建構式不能宣告 super 形式參數。
描述
#當擴展類型中的建構式具有 super 參數時,分析器會產生此診斷訊息。Super 參數是無效的,因為擴展類型沒有超類別。
範例
#以下程式碼會產生此診斷訊息,因為具名建構式 n
包含一個 super 參數
extension type E(int i) {
E.n(this.i, super.foo);
}
常見修正方式
#如果您需要該參數,請將 super 參數替換為常規參數
extension type E(int i) {
E.n(this.i, String foo);
}
如果您不需要該參數,則移除 super 參數
extension type E(int i) {
E.n(this.i);
}
具有_super_調用的擴充功能類型建構子
#擴展類型建構式不能包含 super 初始化器。
描述
#當擴展類型中的建構式在初始化器列表中包含對 super 建構式的調用時,分析器會產生此診斷訊息。由於擴展類型沒有超類別,因此沒有建構式可以調用。
範例
#以下程式碼會產生此診斷訊息,因為建構式 E.n
在其初始化器列表中調用了一個 super 建構式
extension type E(int i) {
E.n() : i = 0, super.n();
}
常見修正方式
#移除對 super 建構式的調用
extension type E(int i) {
E.n() : i = 0;
}
擴充功能類型宣告實例欄位
#擴展類型不能宣告實例欄位。
描述
#當擴展類型宣告的主體中存在欄位宣告時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為擴展類型 E
宣告了一個名為 f
的欄位
extension type E(int i) {
final int f = 0;
}
常見修正方式
#如果您不需要該欄位,則移除它或將其替換為 getter 和/或 setter
extension type E(int i) {
int get f => 0;
}
如果您需要該欄位,則將擴展類型轉換為類別
class E {
final int i;
final int f = 0;
E(this.i);
}
擴充功能類型宣告物件成員
#擴展類型不能宣告與 'Object' 宣告的成員同名的成員。
描述
#當擴展類型宣告的主體包含一個與 Object
宣告的成員之一同名的成員時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為類別 Object
已經定義了一個名為 hashCode
的成員
extension type E(int i) {
int get hashCode => 0;
}
常見修正方式
#如果您需要具有已實現語義的成員,則重新命名成員
extension type E(int i) {
int get myHashCode => 0;
}
如果您不需要具有已實現語義的成員,則移除成員
extension type E(int i) {}
擴充功能類型實作了不允許的類型
#擴展類型不能實現「{0}」。
描述
#當擴展類型實現了它不允許實現的類型時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為擴展類型不能實現類型 dynamic
extension type A(int i) implements dynamic {}
常見修正方式
#從 implements 子句中移除不允許的類型
extension type A(int i) {}
擴充功能類型實作了自身
#擴展類型不能實現自身。
描述
#當擴展類型直接或間接地實現自身時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為擴展類型 A
直接實現了自身
extension type A(int i) implements A {}
以下程式碼會產生此診斷訊息,因為擴展類型 A
間接地實現了自身 (通過 B
)
extension type A(int i) implements B {}
extension type B(int i) implements A {}
常見修正方式
#通過從至少一個涉及循環的類型的 implements 子句中移除一個類型來打破循環
extension type A(int i) implements B {}
extension type B(int i) {}
擴充功能類型實作了非超類型
#「{0}」不是「{1}」的超類型,即表示類型。
描述
#當擴展類型實現的類型不是表示類型的超類型時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為擴展類型 A
實現了 String
,但 String
不是表示類型 int
的超類型
extension type A(int i) implements String {}
常見修正方式
#如果表示類型是正確的,則移除或替換 implements 子句中的類型
extension type A(int i) {}
如果表示類型不正確,則將其替換為正確的類型
extension type A(String s) implements String {}
擴充功能類型實作了表示法非超類型
#「{0}」,「{1}」的表示類型,不是「{2}」,「{3}」的表示類型的超類型。
描述
#當擴展類型實現另一個擴展類型,並且被實現的擴展類型的表示類型不是實現擴展類型的表示類型的子類型時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為擴展類型 B
實現了 A
,但 A
的表示類型 (num
) 不是 B
的表示類型 (String
) 的子類型
extension type A(num i) {}
extension type B(String s) implements A {}
常見修正方式
#更改兩個擴展類型的表示類型,使被實現的類型的表示類型成為實現類型的表示類型的超類型
extension type A(num i) {}
extension type B(int n) implements A {}
或從 implements 子句中移除被實現的類型
extension type A(num i) {}
extension type B(String s) {}
擴充功能類型繼承的成員衝突
#擴展類型「{0}」從已實現的類型中具有多個名為「{1}」的不同成員。
描述
#分析器會在擴充類型實作兩個或多個其他類型,且至少有其中兩個類型宣告了名稱相同的成員時,產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為擴充類型 C
同時實作了 A
和 B
,而兩者都宣告了名為 m
的成員
class A {
void m() {}
}
extension type B(A a) {
void m() {}
}
extension type C(A a) implements A, B {}
常見修正方式
#如果擴充類型不需要實作所有列出的類型,則移除除了其中一個引入衝突成員的類型之外的所有類型
class A {
void m() {}
}
extension type B(A a) {
void m() {}
}
extension type C(A a) implements A {}
如果擴充類型需要實作所有列出的類型,但您可以重新命名這些類型中的成員,則為衝突的成員提供唯一的名稱
class A {
void m() {}
}
extension type B(A a) {
void n() {}
}
extension type C(A a) implements A, B {}
擴充功能類型表示法取決於自身
#擴充類型的表示法不能依賴自身。
描述
#當擴充類型的表示類型直接或間接地依賴擴充類型自身時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為擴充類型 A
的表示類型直接依賴於 A
extension type A(A a) {}
以下兩個程式碼範例會產生此診斷訊息,因為擴充類型 A
的表示類型透過擴充類型 B
間接地依賴於 A
extension type A(B b) {}
extension type B(A a) {}
extension type A(List<B> b) {}
extension type B(List<A> a) {}
常見修正方式
#透過為循環中的至少一個類型選擇不同的表示類型來移除依賴性
extension type A(String s) {}
擴充功能類型表示法類型為底部
#表示類型不能是 bottom type。
描述
#當擴充類型的表示類型是 bottom type Never
時,分析器會產生此診斷訊息。類型 Never
不能作為擴充類型的表示類型,因為沒有可以擴充的值。
範例
#以下程式碼會產生此診斷訊息,因為擴充類型 E
的表示類型是 Never
extension type E(Never n) {}
常見修正方式
#將擴充類型替換為不同的類型
extension type E(String s) {}
具有抽象成員的擴充功能類型
#'{0}' 必須有方法主體,因為 '{1}' 是一個擴充類型。
描述
#當擴充類型宣告抽象成員時,分析器會產生此診斷訊息。由於擴充類型成員的參考是靜態解析的,因此擴充類型中的抽象成員永遠無法執行。
範例
#以下程式碼會產生此診斷訊息,因為擴充類型 E
中的方法 m
是抽象的
extension type E(String s) {
void m();
}
常見修正方式
#如果成員旨在可執行,則提供成員的實作
extension type E(String s) {
void m() {}
}
如果成員不旨在可執行,則移除它
extension type E(String s) {}
具有初始化器的外部
#外部欄位不能有初始化器。
外部變數不能有初始化器。
描述
#當標記為關鍵字 external
的欄位或變數具有初始化器,或者當外部欄位在建構子中初始化時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為外部欄位 x
在初始化器中被賦予值
class C {
external int x;
C() : x = 0;
}
以下程式碼會產生此診斷訊息,因為外部欄位 x
具有初始化器
class C {
external final int x = 0;
}
以下程式碼會產生此診斷訊息,因為外部頂層變數 x
具有初始化器
external final int x = 0;
常見修正方式
#移除初始化器
class C {
external final int x;
}
struct_欄位上多餘的註解
#結構類別中的欄位必須恰好有一個指示原生類型的註解。
描述
#當 Struct
子類別中的欄位具有多個描述欄位原生類型的註解時,分析器會產生此診斷訊息。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼會產生此診斷訊息,因為欄位 x
有兩個描述欄位原生類型的註解
import 'dart:ffi';
final class C extends Struct {
@Int32()
@Int16()
external int x;
}
常見修正方式
#移除除了其中一個註解之外的所有註解
import 'dart:ffi';
final class C extends Struct {
@Int32()
external int x;
}
額外的位置引數
#位置引數過多:預期 {0} 個,但找到 {1} 個。
描述
#當方法或函數調用具有比方法或函數允許的位置引數更多的引數時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 f
定義了 2 個參數,但使用 3 個引數調用
void f(int a, int b) {}
void g() {
f(1, 2, 3);
}
常見修正方式
#移除與參數不對應的引數
void f(int a, int b) {}
void g() {
f(1, 2);
}
額外的位置引數可能是具名的
#位置引數過多:預期 {0} 個,但找到 {1} 個。
描述
#當方法或函數調用具有比方法或函數允許的位置引數更多的引數時,分析器會產生此診斷訊息,但方法或函數定義了具名參數。
範例
#以下程式碼會產生此診斷訊息,因為 f
定義了 2 個位置參數,但有一個具名參數可以用於第三個引數
void f(int a, int b, {int? c}) {}
void g() {
f(1, 2, 3);
}
常見修正方式
#如果某些引數應該是具名參數的值,則在引數之前新增名稱
void f(int a, int b, {int? c}) {}
void g() {
f(1, 2, c: 3);
}
否則,移除與位置參數不對應的引數
void f(int a, int b, {int? c}) {}
void g() {
f(1, 2);
}
carray額外的大小註解
#'Array' 必須恰好有一個 'Array' 註解。
描述
#當 Struct
子類別中的欄位具有多個描述原生陣列大小的註解時,分析器會產生此診斷訊息。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼會產生此診斷訊息,因為欄位 a0
有兩個指定原生陣列大小的註解
import 'dart:ffi';
final class C extends Struct {
@Array(4)
@Array(8)
external Array<Uint8> a0;
}
常見修正方式
#移除除了其中一個註解之外的所有註解
import 'dart:ffi';
final class C extends Struct {
@Array(8)
external Array<Uint8> a0;
}
ffi_native無效的重複預設資源
#一個程式庫最多只能有一個 @DefaultAsset 註解。
描述
#當程式庫指令具有多個與其關聯的 DefaultAsset
註解時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為程式庫指令具有兩個與其關聯的 DefaultAsset
註解
@DefaultAsset('a')
@DefaultAsset('b')
library;
import 'dart:ffi';
常見修正方式
#移除除了其中一個 DefaultAsset
註解之外的所有註解
@DefaultAsset('a')
library;
import 'dart:ffi';
ffi_native無效的多個註解
#原生函數和欄位必須恰好有一個 @Native
註解。
描述
#當單一宣告上有超過一個 Native
註解時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為函數 f
有兩個與其關聯的 Native
註解
import 'dart:ffi';
@Native<Int32 Function(Int32)>()
@Native<Int32 Function(Int32)>(isLeaf: true)
external int f(int v);
常見修正方式
#移除除了其中一個註解之外的所有註解
import 'dart:ffi';
@Native<Int32 Function(Int32)>(isLeaf: true)
external int f(int v);
ffi_native必須是外部的
#原生函數必須宣告為 external。
描述
#當註解為 @Native
的函數未標記為 external
時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為函數 free
註解為 @Native
,但該函數未標記為 external
import 'dart:ffi';
@Native<Void Function(Pointer<Void>)>()
void free(Pointer<Void> ptr) {}
常見修正方式
#如果函數是原生函數,則在返回類型之前新增修飾詞 external
import 'dart:ffi';
@Native<Void Function(Pointer<Void>)>()
external void free(Pointer<Void> ptr);
ffi_native非預期的參數數量
#Native 註解參數的數量不符預期。預期 {0} 個,但有 {1} 個。
描述
#當用作 @Native
註解的類型引數的函數類型中的參數數量與被註解的函數中的參數數量不符時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為用作 @Native
註解的類型引數的函數類型 (Void Function(Double)
) 有一個引數,而被註解的函數的類型 (void f(double, double)
) 有兩個引數
import 'dart:ffi';
@Native<Void Function(Double)>(symbol: 'f')
external void f(double x, double y);
常見修正方式
#如果被註解的函數是正確的,則更新 @Native
註解中的函數類型以匹配
import 'dart:ffi';
@Native<Void Function(Double, Double)>(symbol: 'f')
external void f(double x, double y);
如果 @Native
註解中的函數類型是正確的,則更新被註解的函數以匹配
import 'dart:ffi';
@Native<Void Function(Double)>(symbol: 'f')
external void f(double x);
ffi_native具有接收器的非預期參數數量
#Native 註解參數的數量不符預期。預期 {0} 個,但有 {1} 個。原生實例方法註解必須將接收器作為第一個引數。
描述
#當原生方法的 @Native
註解上使用的類型引數不包含方法接收器的類型時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 @Native
註解上的類型引數 (Void Function(Double)
) 不包含方法接收器的類型
import 'dart:ffi';
class C {
@Native<Void Function(Double)>()
external void f(double x);
}
常見修正方式
#新增一個初始參數,其類型與宣告原生方法的類別相同
import 'dart:ffi';
class C {
@Native<Void Function(C, Double)>()
external void f(double x);
}
由多個初始化器初始化的欄位
#欄位 '{0}' 不能在同一個建構子中初始化兩次。
描述
#當建構子的初始化列表多次初始化一個欄位時,分析器會產生此診斷訊息。允許兩個初始化器沒有任何意義,因為只會保留最後一個值。
範例
#以下程式碼會產生此診斷訊息,因為欄位 f
正在被初始化兩次
class C {
int f;
C() : f = 0, f = 1;
}
常見修正方式
#移除其中一個初始化器
class C {
int f;
C() : f = 0;
}
在初始化器和宣告中初始化的欄位
#如果欄位是 final 且已在其宣告時初始化,則不能在建構子中初始化。
描述
#當 final 欄位在欄位的宣告和建構子中的初始化器中都初始化時,分析器會產生此診斷訊息。Final 欄位只能賦值一次,因此不能在兩個地方都初始化。
範例
#以下程式碼會產生此診斷訊息,因為 f
是
class C {
final int f = 0;
C() : f = 1;
}
常見修正方式
#如果初始化不依賴於傳遞給建構子的任何值,並且如果所有建構子都需要將欄位初始化為相同的值,則從建構子中移除初始化器
class C {
final int f = 0;
C();
}
如果初始化依賴於傳遞給建構子的值,或者如果不同的建構子需要以不同的方式初始化欄位,則從欄位的宣告中移除初始化器
class C {
final int f;
C() : f = 1;
}
在參數和初始化器中初始化的欄位
#欄位不能在參數列表和初始化器中同時初始化。
描述
#當欄位在參數列表和建構子的初始化列表中都初始化時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為欄位 f
同時被初始化形式參數和初始化列表初始化
class C {
int f;
C(this.f) : f = 0;
}
常見修正方式
#如果應該由參數初始化欄位,則移除初始化列表中的初始化
class C {
int f;
C(this.f);
}
如果應該在初始化列表中初始化欄位並且不需要參數,則移除參數
class C {
int f;
C() : f = 0;
}
如果應該在初始化列表中初始化欄位並且需要參數,則將其設為一般參數
class C {
int f;
C(int g) : f = g * 2;
}
欄位初始化器_factory_建構子
#初始化形式參數不能用於 factory 建構子。
描述
#當 factory 建構子具有初始化形式參數時,分析器會產生此診斷訊息。Factory 建構子不能將值賦給欄位,因為沒有建立實例;因此,沒有欄位可以賦值。
範例
#以下程式碼會產生此診斷訊息,因為 factory 建構子使用了初始化形式參數
class C {
int? f;
factory C(this.f) => throw 0;
}
常見修正方式
#將初始化形式參數替換為一般參數
class C {
int? f;
factory C(int f) => throw 0;
}
struct中的欄位初始化器
#'Struct' 和 'Union' 子類別中的建構子不能有欄位初始化器。
描述
#當 Struct
或 Union
的子類別中的建構子具有一個或多個欄位初始化器時,分析器會產生此診斷訊息。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼會產生此診斷訊息,因為類別 C
有一個具有欄位 f
初始化器的建構子
// @dart = 2.9
import 'dart:ffi';
final class C extends Struct {
@Int32()
int f;
C() : f = 0;
}
常見修正方式
#移除欄位初始化器
// @dart = 2.9
import 'dart:ffi';
final class C extends Struct {
@Int32()
int f;
C();
}
欄位初始化器不可賦值
#在 const 建構子中,初始化器類型 '{0}' 無法賦值給欄位類型 '{1}'。
初始化器類型 '{0}' 無法賦值給欄位類型 '{1}'。
描述
#當建構子的初始化列表將欄位初始化為無法賦值給該欄位的值時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 0
的類型為 int
,而 int
無法賦值給類型為 String
的欄位
class C {
String s;
C() : s = 0;
}
常見修正方式
#如果欄位的類型是正確的,則變更賦給它的值,使該值具有有效的類型
class C {
String s;
C() : s = '0';
}
如果值的類型是正確的,則變更欄位的類型以允許賦值
class C {
int s;
C() : s = 0;
}
建構子外部的欄位初始化器
#欄位形式參數只能在建構子中使用。
初始化形式參數只能在建構子中使用。
描述
#當初始化形式參數用於建構子以外的任何參數列表時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為初始化形式參數 this.x
正在方法 m
中使用
class A {
int x = 0;
m([this.x = 0]) {}
}
常見修正方式
#將初始化形式參數替換為一般參數,並在方法主體中賦值給欄位
class A {
int x = 0;
m([int x = 0]) {
this.x = x;
}
}
欄位初始化器重新導向建構子
#重新導向建構子不能有欄位初始化器。
描述
#當重新導向建構子在物件中初始化欄位時,分析器會產生此診斷訊息。這是不允許的,因為在應該初始化欄位時,尚未建立具有該欄位的實例。
範例
#以下程式碼會產生此診斷訊息,因為重新導向到建構子 C
的建構子 C.zero
具有初始化欄位 f
的初始化形式參數
class C {
int f;
C(this.f);
C.zero(this.f) : this(f);
}
以下程式碼會產生此診斷訊息,因為重新導向到建構子 C
的建構子 C.zero
具有初始化欄位 f
的初始化器
class C {
int f;
C(this.f);
C.zero() : f = 0, this(1);
}
常見修正方式
#如果初始化是由初始化形式參數完成的,則使用一般參數
class C {
int f;
C(this.f);
C.zero(int f) : this(f);
}
如果初始化是在初始化器中完成的,則移除初始化器
class C {
int f;
C(this.f);
C.zero() : this(0);
}
欄位初始化形式參數不可賦值
#參數類型 '{0}' 與欄位類型 '{1}' 不相容。
描述
#當初始化形式參數的類型無法賦值給正在初始化的欄位的類型時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為初始化形式參數的類型為 String
,但欄位的類型為 int
。參數的類型必須是欄位類型的子類型。
class C {
int f;
C(String this.f);
}
常見修正方式
#如果欄位的類型不正確,則變更欄位的類型以匹配參數的類型,並考慮從參數中移除類型
class C {
String f;
C(this.f);
}
如果參數的類型不正確,則移除參數的類型
class C {
int f;
C(this.f);
}
如果欄位和參數的類型都正確,則使用初始化器而不是初始化形式參數,將參數值轉換為正確類型的值
class C {
int f;
C(String s) : f = int.parse(s);
}
具有初始化器的_struct中的欄位
#'Struct' 和 'Union' 子類別中的欄位不能有初始化器。
描述
#當 Struct
子類別中的欄位具有初始化器時,分析器會產生此診斷訊息。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼會產生此診斷訊息,因為欄位 p
具有初始化器
// @dart = 2.9
import 'dart:ffi';
final class C extends Struct {
Pointer p = nullptr;
}
常見修正方式
#移除初始化器
// @dart = 2.9
import 'dart:ffi';
final class C extends Struct {
Pointer p;
}
struct中的欄位必須是外部的
#'Struct' 和 'Union' 子類別的欄位必須標記為 external。
描述
#當 Struct
或 Union
的子類別中的欄位未標記為 external
時,分析器會產生此診斷訊息。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼會產生此診斷訊息,因為欄位 a
未標記為 external
import 'dart:ffi';
final class C extends Struct {
@Int16()
int a;
}
常見修正方式
#新增必要的 external
修飾詞
import 'dart:ffi';
final class C extends Struct {
@Int16()
external int a;
}
在宣告和建構子中初始化的_final
#'{0}' 是 final,並且在宣告時已賦予值,因此不能設定為新值。
描述
#當 final 欄位被初始化兩次時,分析器會產生此診斷訊息:一次在其宣告的位置,一次透過建構子的參數。
範例
#以下程式碼會產生此診斷訊息,因為欄位 f
被初始化了兩次
class C {
final int f = 0;
C(this.f);
}
常見修正方式
#如果欄位在所有實例中都應該具有相同的值,則移除參數列表中的初始化
class C {
final int f = 0;
C();
}
如果欄位在不同的實例中可以具有不同的值,則移除宣告中的初始化
class C {
final int f;
C(this.f);
}
final_未初始化
#final 變數 '{0}' 必須初始化。
描述
#當 final 欄位或變數未初始化時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 x
沒有初始化器
final x;
常見修正方式
#對於變數和靜態欄位,您可以新增初始化器
final x = 0;
對於實例欄位,您可以新增初始化器,如先前的範例所示,或者您可以在每個建構子中初始化欄位。您可以使用初始化形式參數來初始化欄位
class C {
final int x;
C(this.x);
}
您也可以透過在建構子中使用初始化器來初始化欄位
class C {
final int x;
C(int y) : x = y * 2;
}
final_未初始化_建構子
#所有 final 變數都必須初始化,但 '{0}' 和 '{1}' 沒有。
所有 final 變數都必須初始化,但 '{0}' 沒有。
所有 final 變數都必須初始化,但 '{0}'、'{1}' 和其他 {2} 個沒有。
描述
#當類別定義了一個或多個沒有初始化器的 final 實例欄位,並且至少有一個建構子沒有初始化這些欄位時,分析器會產生此診斷訊息。所有 final 實例欄位都必須在建立實例時初始化,可以是透過欄位的初始化器或透過建構子。
範例
#下列程式碼會產生此診斷訊息
class C {
final String value;
C();
}
常見修正方式
#如果值應該直接傳遞到建構子中,則使用初始化形式參數來初始化欄位 value
class C {
final String value;
C(this.value);
}
如果值應該從呼叫者提供的值間接計算而來,則新增一個參數並包含一個初始化器
class C {
final String value;
C(Object o) : value = o.toString();
}
如果欄位的值不依賴於可以傳遞給建構子的值,則在欄位宣告中為欄位新增一個初始化器
class C {
final String value = '';
C();
}
如果欄位的值不依賴於可以傳遞給建構子的值,但不同的建構子需要將其初始化為不同的值,則在初始化列表中為欄位新增一個初始化器
class C {
final String value;
C() : value = '';
C.named() : value = 'c';
}
但是,如果該值對於所有實例都相同,則考慮使用靜態欄位而不是實例欄位
class C {
static const String value = '';
C();
}
flutter_欄位不是_map
#'flutter' 欄位的值預期為 map。
描述
#當 flutter
鍵的值不是 map 時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為頂層 flutter
鍵的值是字串
name: example
flutter: true
常見修正方式
#如果您需要指定 Flutter 特定的選項,則將值變更為 map
name: example
flutter:
uses-material-design: true
如果您不需要指定 Flutter 特定的選項,則移除 flutter
鍵
name: example
for-in_的無效元素類型
#'for' 迴圈中使用的類型 '{0}' 必須實作 '{1}',且其類型引數可以賦值給 '{2}'。
描述
#當 for-in 迴圈中的 Iterable
或 Stream
具有無法賦值給迴圈變數的元素類型時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 <String>[]
的元素類型為 String
,而 String
無法賦值給 e
的類型 (int
)
void f() {
for (int e in <String>[]) {
print(e);
}
}
常見修正方式
#如果迴圈變數的類型是正確的,則更新 iterable 的類型
void f() {
for (int e in <int>[]) {
print(e);
}
}
如果 iterable 的類型是正確的,則更新迴圈變數的類型
void f() {
for (String e in <String>[]) {
print(e);
}
}
for-in_的無效類型
#'for' 迴圈中使用的類型 '{0}' 必須實作 '{1}'。
描述
#當 for-in 迴圈中 in
後面的表達式具有不是 Iterable
子類別的類型時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 m
是 Map
,而 Map
不是 Iterable
的子類別
void f(Map<String, String> m) {
for (String s in m) {
print(s);
}
}
常見修正方式
#將表達式替換為產生 iterable 值的表達式
void f(Map<String, String> m) {
for (String s in m.values) {
print(s);
}
}
具有_const_變數的_for-in
#for-in 迴圈變數不能是 'const'。
描述
#當在 for-in 迴圈中宣告的迴圈變數被宣告為 const
時,分析器會產生此診斷訊息。變數不能是 const
,因為該值無法在編譯時計算。
範例
#以下程式碼會產生此診斷訊息,因為迴圈變數 x
被宣告為 const
void f() {
for (const x in [0, 1, 2]) {
print(x);
}
}
常見修正方式
#如果存在類型註解,則從宣告中移除 const
修飾詞。
如果沒有類型,則將 const
修飾詞替換為 final
、var
或類型註解
void f() {
for (final x in [0, 1, 2]) {
print(x);
}
}
dynamic上的泛型方法類型具現化
#類型為 'dynamic' 的接收器的成員方法 tear-off 不能有類型引數。
描述
#當從類型為 dynamic
的接收器 tear-off 實例方法,並且 tear-off 包含類型引數時,分析器會產生此診斷訊息。由於分析器無法知道該方法有多少個類型參數,或者它是否具有任何類型參數,因此無法驗證類型引數是否正確。因此,不允許使用類型引數。
範例
#以下程式碼會產生此診斷訊息,因為 p
的類型為 dynamic
,並且 m
的 tear-off 具有類型引數
void f(dynamic list) {
list.fold<int>;
}
常見修正方式
#如果您可以使用比 dynamic
更具體的類型,則變更接收器的類型
void f(List<Object> list) {
list.fold<int>;
}
如果您無法使用更具體的類型,則移除類型引數
void f(dynamic list) {
list.cast;
}
泛型_struct_子類別
#類別 '{0}' 無法擴展 'Struct' 或 'Union',因為 '{0}' 是泛型類別。
描述
#當 Struct
或 Union
的子類別具有類型參數時,分析器會產生此診斷訊息。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼會產生此診斷訊息,因為類別 S
定義了類型參數 T
import 'dart:ffi';
final class S<T> extends Struct {
external Pointer notEmpty;
}
常見修正方式
#從類別中移除類型參數
import 'dart:ffi';
final class S extends Struct {
external Pointer notEmpty;
}
getter不是_setter類型的子類型
#getter '{0}' 的返回類型為 '{1}',這不是其 setter '{3}' 的類型 '{2}' 的子類型。
描述
#當 getter 的返回類型不是與其同名的 setter 的參數類型的子類型時,分析器會產生此診斷訊息。
子類型關係是一個要求,無論 getter 和 setter 是否在同一個類別中,或者它們中的一個是否在另一個的父類別中。
範例
#以下程式碼會產生此診斷訊息,因為 getter x
的返回類型為 num
,setter x
的參數類型為 int
,而 num
不是 int
的子類型
class C {
num get x => 0;
set x(int y) {}
}
常見修正方式
#如果 getter 的類型是正確的,則變更 setter 的類型
class C {
num get x => 0;
set x(num y) {}
}
如果 setter 的類型是正確的,則變更 getter 的類型
class C {
int get x => 0;
set x(int y) {}
}
非法的_async_產生器傳回類型
#標記為 'async*' 的函數必須具有作為 'Stream
描述
#當函數的主體具有 async*
修飾詞,即使函數的返回類型不是 Stream
或 Stream
的超類型時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為函數 f
的主體具有 'async*' 修飾詞,即使返回類型 int
不是 Stream
的超類型
int f() async* {}
常見修正方式
#如果函數應該是非同步的,則將返回類型變更為 Stream
或 Stream
的超類型
Stream<int> f() async* {}
如果函數應該是同步的,則移除 async*
修飾詞
int f() => 0;
非法的_async傳回類型
#標記為 'async' 的函數必須具有作為 'Future' 的超類型的返回類型。
描述
#當函數的主體具有 async
修飾詞,即使函數的返回類型無法賦值給 Future
時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為函數 f
的主體具有 async
修飾詞,即使返回類型無法賦值給 Future
int f() async {
return 0;
}
常見修正方式
#如果函數應該是非同步的,則將返回類型變更為可賦值給 Future
的類型
Future<int> f() async {
return 0;
}
如果函數應該是同步的,則移除 async
修飾詞
int f() => 0;
非法的具體列舉成員
#名為 '{0}' 的具體實例成員不能在實作 'Enum' 的類別中宣告。
名為 '{0}' 的具體實例成員不能從實作 'Enum' 的類別中的 '{1}' 繼承。
描述
#當列舉宣告、實作 Enum
的類別,或具有 Enum
超類別約束的 mixin,宣告或繼承名為 index
、hashCode
或 ==
的具體實例成員時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為列舉 E
宣告了一個名為 index
的實例 getter
enum E {
v;
int get index => 0;
}
以下程式碼會產生此診斷訊息,因為實作 Enum
的類別 C
宣告了一個名為 hashCode
的實例欄位
abstract class C implements Enum {
int hashCode = 0;
}
以下程式碼會產生此診斷訊息,因為透過類別 A
間接實作 Enum
的類別 C
宣告了一個名為 hashCode
的實例 getter
abstract class A implements Enum {}
abstract class C implements A {
int get hashCode => 0;
}
以下程式碼會產生此診斷訊息,因為在 on
子句中具有 Enum
的 mixin M
宣告了一個明確的運算子 ==
mixin M on Enum {
bool operator ==(Object other) => false;
}
常見修正方式
#重新命名衝突的成員
enum E {
v;
int get getIndex => 0;
}
非法的列舉值
#名為 'values' 的實例成員不能在實作 'Enum' 的類別中宣告。
名為 'values' 的實例成員不能從實作 'Enum' 的類別中的 '{0}' 繼承。
描述
#當實作 Enum
的類別或具有 Enum
超類別約束的 mixin 具有名為 values
的實例成員時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為實作 Enum
的類別 C
宣告了一個名為 values
的實例欄位
abstract class C implements Enum {
int get values => 0;
}
以下程式碼會產生此診斷訊息,因為實作 Enum
的類別 B
從 A
繼承了一個名為 values
的實例方法
abstract class A {
int values() => 0;
}
abstract class B extends A implements Enum {}
常見修正方式
#變更衝突成員的名稱
abstract class C implements Enum {
int get value => 0;
}
非法的_sync_產生器傳回類型
#標記為 'sync*' 的函數必須具有作為 'Iterable
描述
#分析器會在函數的主體具有 sync*
修飾詞,即使函數的返回類型不是 Iterable
或 Iterable
的超類型時,產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為函數 f
的主體具有 'sync*' 修飾詞,即使返回類型 int
不是 Iterable
的超類型
int f() sync* {}
常見修正方式
#如果函數應該返回 iterable,則將返回類型變更為 Iterable
或 Iterable
的超類型
Iterable<int> f() sync* {}
如果函數應該返回單一值,則移除 sync*
修飾詞
int f() => 0;
實作非類別
#類別和 mixin 只能實作其他類別和 mixin。
描述
#當在類別或 mixin 宣告的 implements
子句中使用的名稱被定義為類別或 mixin 以外的其他內容時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 x
是一個變數而不是類別或 mixin
var x;
class C implements x {}
常見修正方式
#如果該名稱是已經匯入的現有類別或 mixin 的名稱,則為匯入新增前綴,以便該名稱的本地定義不會遮蔽匯入的名稱。
如果該名稱是未匯入的現有類別或 mixin 的名稱,則為宣告它的程式庫新增帶有前綴的匯入。
否則,將 implements
子句中的名稱替換為現有類別或 mixin 的名稱,或從 implements
子句中移除該名稱。
重複實作
#'{0}' 只能實作一次。
描述
#當在 implements
子句中多次指定同一個類別時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 A
在列表中出現兩次
class A {}
class B implements A, A {}
常見修正方式
#移除除了其中一個類別名稱之外的所有名稱
class A {}
class B implements A {}
實作父類別
#'{0}' 不能同時在 'extends' 和 'implements' 子句中使用。
'{0}' 不能同時在 'extends' 和 'with' 子句中使用。
描述
#當類別在類別宣告的 extends
子句中列出,並且同時在同一個宣告的 implements
或 with
子句中列出時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為類別 A
同時用於類別 B
的 extends
和 implements
子句中
class A {}
class B extends A implements A {}
以下程式碼會產生此診斷訊息,因為類別 A
同時用於類別 B
的 extends
和 with
子句中
mixin class A {}
class B extends A with A {}
常見修正方式
#如果您想要從類別繼承實作,則從 implements
子句中移除該類別
class A {}
class B extends A {}
如果您不想要從類別繼承實作,則移除 extends
子句
class A {}
class B implements A {}
隱含_super_初始化器遺失引數
#從 '{0}' 隱含調用的未命名建構子具有必要參數。
描述
#當建構子隱含調用來自父類別的未命名建構子,父類別的未命名建構子具有必要參數,並且沒有與必要參數對應的 super 參數時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為類別 B
中的未命名建構子隱含調用類別 A
中的未命名建構子,但 A
中的建構子具有名為 x
的必要位置參數
class A {
A(int x);
}
class B extends A {
B();
}
以下程式碼會產生此診斷訊息,因為類別 B
中的未命名建構子隱含調用類別 A
中的未命名建構子,但 A
中的建構子具有名為 x
的必要具名參數
class A {
A({required int x});
}
class B extends A {
B();
}
常見修正方式
#如果您可以在子類別的建構子中新增參數,則新增與父類別建構子中必要參數對應的 super 參數。新的參數可以是必要的
class A {
A({required int x});
}
class B extends A {
B({required super.x});
}
或者它可以是選用的
class A {
A({required int x});
}
class B extends A {
B({super.x = 0});
}
如果您無法在子類別的建構子中新增參數,則新增具有必要引數的明確 super 建構子調用
class A {
A(int x);
}
class B extends A {
B() : super(0);
}
初始化器中隱含的_this_參考
#實例成員 '{0}' 無法在初始化器中存取。
描述
#當分析器在建構子的初始化列表中找到對實例成員的參考時,會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 defaultX
是一個實例成員
class C {
int x;
C() : x = defaultX;
int get defaultX => 0;
}
常見修正方式
#如果成員可以設為靜態,則這樣做
class C {
int x;
C() : x = defaultX;
static int get defaultX => 0;
}
如果不是,則將初始化器中的參考替換為不使用實例成員的不同表達式
class C {
int x;
C() : x = 0;
int get defaultX => 0;
}
具有載入函式的延遲載入程式庫匯入
#匯入的程式庫定義了一個名為 'loadLibrary' 的頂層函數,該函數被延遲此程式庫而隱藏。
描述
#當宣告了名為 loadLibrary
的函數的程式庫使用延遲匯入來匯入時,分析器會產生此診斷訊息。延遲匯入引入了一個名為 loadLibrary
的隱含函數。此函數用於載入延遲程式庫的內容,並且隱含函數會隱藏延遲程式庫中的明確宣告。
有關更多資訊,請查看 延遲載入程式庫。
範例
#給定一個定義了名為 loadLibrary
的函數的檔案 a.dart
void loadLibrary(Library library) {}
class Library {}
以下程式碼會產生此診斷訊息,因為 a.loadLibrary
的隱含宣告正在隱藏 a.dart
中 loadLibrary
的明確宣告
import 'a.dart' deferred as a;
void f() {
a.Library();
}
常見修正方式
#如果不需要延遲匯入匯入的程式庫,則移除關鍵字 deferred
import 'a.dart' as a;
void f() {
a.Library();
}
如果需要延遲匯入匯入的程式庫,並且您需要參考匯入的函數,則重新命名匯入的程式庫中的函數
void populateLibrary(Library library) {}
class Library {}
如果需要延遲匯入匯入的程式庫,並且您不需要參考匯入的函數,則新增 hide
子句
import 'a.dart' deferred as a hide loadLibrary;
void f() {
a.Library();
}
匯入內部程式庫
#程式庫 '{0}' 是內部程式庫,無法匯入。
描述
#當分析器找到其 dart:
URI 參考內部程式庫的匯入時,會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 _interceptors
是一個內部程式庫
import 'dart:_interceptors';
常見修正方式
#移除匯入指令。
將舊版程式庫匯入至空值安全程式庫
#程式庫 '{0}' 是舊版程式庫,不應匯入到 null safe 程式庫中。
描述
#當 null safe 程式庫匯入非 null safe 程式庫時,分析器會產生此診斷訊息。
範例
#給定一個包含以下內容的檔案 a.dart
// @dart = 2.9
class A {}
以下程式碼會產生此診斷訊息,因為 null safe 程式庫正在匯入非 null safe 程式庫
import 'a.dart';
A? f() => null;
常見修正方式
#如果您可以將匯入的程式庫遷移到 null safe,則遷移它並更新或移除遷移程式庫的語言版本。
如果您無法遷移匯入的程式庫,則匯入程式庫需要具有在 2.12 之前的語言版本,當時預設啟用 null safety。
匯入非程式庫
#匯入的程式庫 '{0}' 不能有 part-of 指令。
描述
#當 part 檔案 匯入到程式庫中時,分析器會產生此診斷訊息。
範例
#給定一個名為 part.dart
的 part 檔案,其中包含以下內容
part of lib;
以下程式碼會產生此診斷訊息,因為匯入的檔案不能有 part-of 指令
library lib;
import 'part.dart';
常見修正方式
#不一致的繼承
#超介面對於 '{0}' 沒有有效的覆寫:{1}。
描述
#當一個類別繼承了成員的兩個或多個衝突簽名,且沒有提供滿足所有繼承簽名的實作時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 C
從 A
繼承了 m
的宣告,而該實作與從 B
繼承的 m
簽名不一致。
class A {
void m({int? a}) {}
}
class B {
void m({int? b}) {}
}
class C extends A implements B {
}
常見修正方式
#新增一個方法的實作,以滿足所有繼承的簽名。
class A {
void m({int? a}) {}
}
class B {
void m({int? b}) {}
}
class C extends A implements B {
void m({int? a, int? b}) {}
}
不一致的語言版本覆寫
#部分檔案必須與程式庫具有完全相同的語言版本覆寫。
描述
#當部分檔案的語言版本覆寫註解指定的語言版本,與部分檔案所屬程式庫使用的語言版本不同時,分析器會產生此診斷訊息。
範例
#假設有一個名為 part.dart
的部分檔案,其中包含以下內容:
// @dart = 2.14
part of 'test.dart';
以下程式碼會產生此診斷訊息,因為程式庫的部分檔案必須與定義編譯單元具有相同的語言版本。
// @dart = 2.15
part 'part.dart';
常見修正方式
#從部分檔案中移除語言版本覆寫,使其隱含地使用與定義編譯單元相同的版本。
part of 'test.dart';
如有必要,調整定義編譯單元中的語言版本覆寫,使其適用於部分檔案中的程式碼,或者將部分檔案中的程式碼遷移為與新的語言版本一致。
不一致的模式變數邏輯或
#變數 '{0}' 在邏輯或模式的這個分支中具有不同的類型和/或最終性。
描述
#當在邏輯或模式的所有分支上宣告的模式變數,在每個分支上沒有相同的類型時,分析器會產生此診斷訊息。當變數在不同分支上具有不同的最終性時,也會產生此訊息。在邏輯或模式的多個分支上宣告的模式變數,在每個分支中都必須具有相同的類型和最終性,以便在受邏輯或模式保護的程式碼中可以知道變數的類型和最終性。
範例
#以下程式碼會產生此診斷訊息,因為變數 a
在一個分支中定義為 int
,而在另一個分支中定義為 double
。
void f(Object? x) {
if (x case (int a) || (double a)) {
print(a);
}
}
以下程式碼會產生此診斷訊息,因為變數 a
在第一個分支中是 final
,而在第二個分支中不是 final
。
void f(Object? x) {
if (x case (final int a) || (int a)) {
print(a);
}
}
常見修正方式
#如果變數的最終性不同,請決定它應該是 final
或非 final
,並使情況保持一致。
void f(Object? x) {
if (x case (int a) || (int a)) {
print(a);
}
}
如果變數的類型不同,且類型對於要匹配的條件並非至關重要,則請確保變數在兩個分支上都具有相同的類型。
void f(Object? x) {
if (x case (num a) || (num a)) {
print(a);
}
}
如果變數的類型不同,且類型對於要匹配的條件至關重要,則請考慮將條件分解為多個 if
語句或 case
子句。
void f(Object? x) {
if (x case int a) {
print(a);
} else if (x case double a) {
print(a);
}
}
不存在欄位的初始化器
#'{0}' 不是封閉類別中的欄位。
描述
#當建構子初始化一個未在包含該建構子的類別中宣告的欄位時,分析器會產生此診斷訊息。建構子無法初始化未宣告的欄位以及從超類別繼承的欄位。
範例
#以下程式碼會產生此診斷訊息,因為初始化器正在初始化 x
,但 x
不是類別中的欄位。
class C {
int? y;
C() : x = 0;
}
常見修正方式
#如果應該初始化不同的欄位,則將名稱更改為欄位的名稱。
class C {
int? y;
C() : y = 0;
}
如果必須宣告欄位,則新增宣告。
class C {
int? x;
int? y;
C() : x = 0;
}
靜態欄位的初始化器
#'{0}' 是封閉類別中的靜態欄位。在建構子中初始化的欄位不能是靜態的。
描述
#當靜態欄位在建構子中使用初始化形式參數或初始化列表中的賦值進行初始化時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為靜態欄位 a
正在由初始化形式參數 this.a
初始化。
class C {
static int? a;
C(this.a);
}
常見修正方式
#如果欄位應該是實例欄位,則移除關鍵字 static
。
class C {
int? a;
C(this.a);
}
如果您打算初始化實例欄位但輸入了錯誤的名稱,則更正要初始化的欄位的名稱。
class C {
static int? a;
int? b;
C(this.b);
}
如果您真的想要初始化靜態欄位,則將初始化移至建構子主體中。
class C {
static int? a;
C(int? c) {
a = c;
}
}
不存在欄位的初始化形式參數
#'{0}' 不是封閉類別中的欄位。
描述
#當在未宣告要初始化的欄位的類別中的建構子中找到初始化形式參數時,分析器會產生此診斷訊息。建構子無法初始化未宣告的欄位以及從超類別繼承的欄位。
範例
#以下程式碼會產生此診斷訊息,因為未定義欄位 x
。
class C {
int? y;
C(this.x);
}
常見修正方式
#如果欄位名稱錯誤,則將其更改為現有欄位的名稱。
class C {
int? y;
C(this.y);
}
如果欄位名稱正確但尚未定義,則宣告該欄位。
class C {
int? x;
int? y;
C(this.x);
}
如果需要參數但不應初始化欄位,則將其轉換為一般參數並使用它。
class C {
int y;
C(int x) : y = x * 2;
}
如果不需要參數,則移除它。
class C {
int? y;
C();
}
實例存取靜態成員
#無法透過實例存取靜態 {1} '{0}'。
描述
#當使用存取運算子透過類別的實例存取靜態成員時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 zero
是一個靜態欄位,但它被當作實例欄位存取。
void f(C c) {
c.zero;
}
class C {
static int zero = 0;
}
常見修正方式
#使用類別來存取靜態成員。
void f(C c) {
C.zero;
}
class C {
static int zero = 0;
}
來自_factory的實例成員存取
#無法從工廠建構子存取實例成員。
描述
#當工廠建構子包含對實例成員的非限定引用時,分析器會產生此診斷訊息。在生成式建構子中,類別的實例在建構子的主體執行之前被建立和初始化,因此實例可以綁定到 this
並像在實例方法中一樣存取。但是,在工廠建構子中,實例在執行主體之前不會被建立,因此無法使用 this
來引用它。
範例
#以下程式碼會產生此診斷訊息,因為 x
在工廠建構子中不在作用域內。
class C {
int x;
factory C() {
return C._(x);
}
C._(this.x);
}
常見修正方式
#重寫程式碼,使其不引用實例成員。
class C {
int x;
factory C() {
return C._(0);
}
C._(this.x);
}
來自靜態的實例成員存取
#無法從靜態方法存取實例成員。
描述
#當靜態方法包含對實例成員的非限定引用時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為實例欄位 x
正在靜態方法中被引用。
class C {
int x = 0;
static int m() {
return x;
}
}
常見修正方式
#如果方法必須引用實例成員,則它不能是靜態的,因此移除關鍵字。
class C {
int x = 0;
int m() {
return x;
}
}
如果方法不能設為實例方法,則新增一個參數,以便可以傳入類別的實例。
class C {
int x = 0;
static int m(C c) {
return c.x;
}
}
具現化抽象類別
#抽象類別無法被實例化。
描述
#當分析器找到建構子調用,且該建構子在抽象類別中宣告時,會產生此診斷訊息。即使您無法建立抽象類別的實例,抽象類別也可以宣告可以被子類別調用的建構子。
範例
#以下程式碼會產生此診斷訊息,因為 C
是一個抽象類別。
abstract class C {}
var c = new C();
常見修正方式
#如果有可以使用的抽象類別的具體子類別,則建立具體子類別的實例。
具現化列舉
#列舉無法被實例化。
描述
#當列舉被實例化時,分析器會產生此診斷訊息。透過調用建構子來建立列舉的實例是無效的;只有在列舉宣告中命名的實例才能存在。
範例
#以下程式碼會產生此診斷訊息,因為列舉 E
正在被實例化。
// @dart = 2.16
enum E {a}
var e = E();
常見修正方式
#如果您打算使用列舉的實例,則引用在列舉中定義的常數之一。
// @dart = 2.16
enum E {a}
var e = E.a;
如果您打算使用類別的實例,則使用該類別的名稱來代替列舉的名稱。
類型別名展開為類型參數
#展開為型別參數的型別別名無法被實例化。
描述
#當找到建構子調用,且要實例化的型別是型別別名的型別參數之一的型別別名時,分析器會產生此診斷訊息。這是不允許的,因為型別參數的值是一個型別而不是一個類別。
範例
#以下程式碼會產生此診斷訊息,因為它建立 A
的實例,即使 A
是一個定義為等效於型別參數的型別別名。
typedef A<T> = T;
void f() {
const A<int>();
}
常見修正方式
#使用類別名稱或定義為類別的型別別名,而不是定義為型別參數的型別別名。
typedef A<T> = C<T>;
void f() {
const A<int>();
}
class C<T> {
const C();
}
整數字面值作為雙精度浮點數不精確
#整數文字正在用作 double,但無法表示為 64 位元 double 而不會溢位或損失精確度:'{0}'。
描述
#當整數文字被隱含地轉換為 double,但無法表示為 64 位元 double 而不會溢位或損失精確度時,分析器會產生此診斷訊息。如果上下文需要 double
類型,則整數文字會隱含地轉換為 double。
範例
#以下程式碼會產生此診斷訊息,因為整數值 9223372036854775807
無法精確地表示為 double。
double x = 9223372036854775807;
常見修正方式
#如果您需要使用精確值,則使用類別 BigInt
來表示該值。
var x = BigInt.parse('9223372036854775807');
如果您需要使用 double,則將值更改為可以精確表示的值。
double x = 9223372036854775808;
整數字面值超出範圍
#整數文字 {0} 無法以 64 位元表示。
描述
#當整數文字的值太大(正數)或太小(負數)而無法以 64 位元字組表示時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為該值無法以 64 位元表示。
var x = 9223372036854775810;
常見修正方式
#如果您需要表示目前的值,則將其包裝在類別 BigInt
的實例中。
var x = BigInt.parse('9223372036854775810');
無效的註解
#註解必須是常數變數引用或常數建構子調用。
描述
#當找到一個註解,它正在使用既不是標記為 const
的變數,也不是 const
建構子的調用時,分析器會產生此診斷訊息。
Getter 不能用作註解。
範例
#以下程式碼會產生此診斷訊息,因為變數 v
不是 const
變數。
var v = 0;
@v
void f() {
}
以下程式碼會產生此診斷訊息,因為 f
不是變數。
@f
void f() {
}
以下程式碼會產生此診斷訊息,因為 f
不是建構子。
@f()
void f() {
}
以下程式碼會產生此診斷訊息,因為 g
是一個 getter。
@g
int get g => 0;
常見修正方式
#如果註解正在引用一個不是 const
建構子的變數,則將關鍵字 const
新增到變數的宣告中。
const v = 0;
@v
void f() {
}
如果註解沒有引用變數,則移除它。
int v = 0;
void f() {
}
來自延遲載入程式庫的無效註解常數值
#來自延遲載入程式庫的常數值不能在註解中使用。
描述
#當在註解的引數列表中引用了在作為延遲載入程式庫匯入的程式庫中定義的常數時,分析器會產生此診斷訊息。註解在編譯時評估,而來自延遲載入程式庫的值在編譯時不可用。
有關更多資訊,請查看 延遲載入程式庫。
範例
#以下程式碼會產生此診斷訊息,因為常數 pi
正在註解的引數列表中被引用,即使定義它的程式庫正在作為延遲載入程式庫匯入。
import 'dart:math' deferred as math;
class C {
const C(double d);
}
@C(math.pi)
void f () {}
常見修正方式
#如果您需要引用匯入的常數,則移除 deferred
關鍵字。
import 'dart:math' as math;
class C {
const C(double d);
}
@C(math.pi)
void f () {}
如果匯入必須是延遲的,並且有另一個適當的常數,則使用該常數代替來自延遲載入程式庫的常數。
來自延遲載入程式庫的無效註解
#來自延遲載入程式庫的常數值不能用作註解。
描述
#當來自使用延遲匯入匯入的程式庫的常數被用作註解時,分析器會產生此診斷訊息。註解在編譯時評估,而來自延遲載入程式庫的常數在編譯時不可用。
有關更多資訊,請查看 延遲載入程式庫。
範例
#以下程式碼會產生此診斷訊息,因為當程式庫 dart:math
以 deferred
形式匯入時,常數 pi
被用作註解。
import 'dart:math' deferred as math;
@math.pi
void f() {}
常見修正方式
#如果您需要將常數作為註解引用,則從匯入中移除關鍵字 deferred
。
import 'dart:math' as math;
@math.pi
void f() {}
如果您可以使用不同的常數作為註解,則將註解替換為不同的常數。
@deprecated
void f() {}
無效的註解目標
#註解 '{0}' 只能在 {1} 上使用。
描述
#當註解應用於它不支持的宣告種類時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 optionalTypeArgs
註解未定義為對頂層變數有效。
import 'package:meta/meta.dart';
@optionalTypeArgs
int x = 0;
常見修正方式
#從宣告中移除註解。
無效的賦值
#類型為 '{0}' 的值無法指派給類型為 '{1}' 的變數。
描述
#當指派給變數的表達式的靜態類型無法指派給變數的類型時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為初始化器 (int
) 的類型無法指派給變數 (String
) 的類型。
int i = 0;
String s = i;
常見修正方式
#如果被指派的值在運行時始終可指派,即使靜態類型沒有反映這一點,則新增明確的類型轉換。
否則,更改被指派的值,使其具有預期的類型。在先前的範例中,這可能看起來像:
int i = 0;
String s = i.toString();
如果您無法更改值,則更改變數的類型,使其與被指派的值的類型相容。
int i = 0;
int s = i;
無效的相依性
#可發布的套件不能有 '{0}' 依賴項。
描述
#當可發布的套件在其 pubspec.yaml
檔案的 dependencies
列表中包含一個不是 pub 託管依賴項的套件時,分析器會產生此診斷訊息。
要了解有關不同類型依賴項來源的更多資訊,請查看 套件依賴項。
範例
#以下程式碼會產生此診斷訊息,因為對套件 transmogrify
的依賴項不是 pub 託管依賴項。
name: example
dependencies:
transmogrify:
path: ../transmogrify
常見修正方式
#如果您想將套件發布到 pub.dev
,則將依賴項更改為在 pub.dev
上發布的託管套件。
如果套件不打算發布到 pub.dev
,則在其 pubspec.yaml
檔案中新增 publish_to: none
條目,以將其標記為不打算發布。
name: example
publish_to: none
dependencies:
transmogrify:
path: ../transmogrify
無效的例外值
#當函數的回傳類型為 'void'、'Handle' 或 'Pointer' 時,方法 {0} 不能有例外回傳值(第二個引數)。
描述
#當方法 Pointer.fromFunction
或 NativeCallable.isolateLocal
的調用具有第二個引數(例外回傳值),且從調用回傳的類型為 void
、Handle
或 Pointer
時,分析器會產生此診斷訊息。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼會產生此診斷訊息,因為當 f
的回傳類型為 void
時,提供了第二個引數。
import 'dart:ffi';
typedef T = Void Function(Int8);
void f(int i) {}
void g() {
Pointer.fromFunction<T>(f, 42);
}
常見修正方式
#移除例外值。
import 'dart:ffi';
typedef T = Void Function(Int8);
void f(int i) {}
void g() {
Pointer.fromFunction<T>(f);
}
無效的內部元素匯出
#成員 '{0}' 不能作為套件公有 API 的一部分匯出。
描述
#當公有程式庫匯出一個標記有 internal
註解的宣告時,分析器會產生此診斷訊息。
範例
#假設在 src
目錄中有一個檔案 a.dart
,其中包含:
import 'package:meta/meta.dart';
@internal class One {}
當在公有程式庫中找到以下程式碼時,會產生此診斷訊息,因為 export
指令正在匯出一個僅供內部使用的名稱。
export 'src/a.dart';
常見修正方式
#如果需要匯出,則新增一個 hide
子句以隱藏內部名稱。
export 'src/a.dart' hide One;
如果不需要匯出,則移除它。
間接無效的內部元素匯出
#成員 '{0}' 不能作為套件公有 API 的一部分匯出,但作為 '{1}' 簽名的一部分間接匯出。
描述
#當公有程式庫匯出一個頂層函數,其回傳類型或至少一個參數類型標記有 internal
註解時,分析器會產生此診斷訊息。
範例
#假設在 src
目錄中有一個檔案 a.dart
,其中包含以下內容:
import 'package:meta/meta.dart';
@internal
typedef IntFunction = int Function();
int f(IntFunction g) => g();
以下程式碼會產生此診斷訊息,因為函數 f
具有類型為 IntFunction
的參數,而 IntFunction
僅供內部使用。
export 'src/a.dart' show f;
常見修正方式
#如果函數必須是公有的,則使函數簽名中的所有類型都成為公有類型。
如果函數不需要匯出,則停止匯出它,可以透過從 show
子句中移除它、將其新增到 hide
子句中,或移除匯出來實現。
無效的擴充功能引數計數
#擴充功能覆寫必須恰好有一個引數:擴充方法中 'this' 的值。
描述
#當擴充功能覆寫沒有恰好一個引數時,分析器會產生此診斷訊息。該引數是用於計算擴充方法中 this
值的表達式,因此必須有一個引數。
範例
#以下程式碼會產生此診斷訊息,因為沒有引數。
extension E on String {
String join(String other) => '$this $other';
}
void f() {
E().join('b');
}
並且,以下程式碼會產生此診斷訊息,因為有多個引數。
extension E on String {
String join(String other) => '$this $other';
}
void f() {
E('a', 'b').join('c');
}
常見修正方式
#為擴充功能覆寫提供一個引數。
extension E on String {
String join(String other) => '$this $other';
}
void f() {
E('a').join('b');
}
無效的_factory_方法宣告
#工廠方法 '{0}' 必須具有回傳類型。
描述
#當標記有 factory
註解的方法具有 void
的回傳類型時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為方法 createC
標記有 factory
註解,但沒有回傳任何值。
import 'package:meta/meta.dart';
class Factory {
@factory
void createC() {}
}
class C {}
常見修正方式
#將回傳類型更改為 void
以外的類型。
import 'package:meta/meta.dart';
class Factory {
@factory
C createC() => C();
}
class C {}
無效的_factory_方法實作
#工廠方法 '{0}' 沒有回傳新分配的物件。
描述
#當標記有 factory
註解的方法沒有回傳新分配的物件時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為方法 createC
回傳欄位的值,而不是新建立的 C
實例。
import 'package:meta/meta.dart';
class Factory {
C c = C();
@factory
C createC() => c;
}
class C {}
常見修正方式
#將方法更改為回傳新建立的回傳類型實例。
import 'package:meta/meta.dart';
class Factory {
@factory
C createC() => C();
}
class C {}
無效的_factory_名稱不是類別
#工廠建構子的名稱必須與直接封閉類別的名稱相同。
描述
#當工廠建構子的名稱與周圍類別的名稱不同時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為工廠建構子的名稱 (A
) 與周圍類別 (C
) 的名稱不同。
class A {}
class C {
factory A() => throw 0;
}
常見修正方式
#如果工廠回傳周圍類別的實例,並且您打算使其成為未命名的工廠建構子,則重新命名工廠。
class A {}
class C {
factory C() => throw 0;
}
如果工廠回傳周圍類別的實例,並且您打算使其成為命名的工廠建構子,則在工廠建構子的名稱前加上周圍類別的名稱。
class A {}
class C {
factory C.a() => throw 0;
}
如果工廠回傳不同類別的實例,則將工廠移至該類別。
class A {
factory A() => throw 0;
}
class C {}
如果工廠回傳不同類別的實例,但您無法修改該類別或不想移動工廠,則將其轉換為靜態方法。
class A {}
class C {
static A a() => throw 0;
}
無效的欄位名稱
#當整數是位置欄位的索引時,記錄欄位名稱不能是錢字符號後跟一個整數。
記錄欄位名稱不能是私有的。
記錄欄位名稱不能與 'Object' 中的成員相同。
描述
#當記錄文字或記錄類型註解具有一個欄位,其名稱無效時,分析器會產生此診斷訊息。如果名稱是以下情況,則無效:
- 私有的 (以
_
開頭) - 與在
Object
上定義的成員之一相同 - 與位置欄位的名稱相同(如果欄位是具有指定名稱的位置欄位,則會例外)
範例
#以下程式碼會產生此診斷訊息,因為記錄文字具有一個名為 toString
的欄位,它是 Object
上定義的方法。
var r = (a: 1, toString: 4);
以下程式碼會產生此診斷訊息,因為記錄類型註解具有一個名為 hashCode
的欄位,它是 Object
上定義的 getter。
void f(({int a, int hashCode}) r) {}
以下程式碼會產生此診斷訊息,因為記錄文字具有一個私有欄位,名為 _a
。
var r = (_a: 1, b: 2);
以下程式碼會產生此診斷訊息,因為記錄類型註解具有一個私有欄位,名為 _a
。
void f(({int _a, int b}) r) {}
以下程式碼會產生此診斷訊息,因為記錄文字具有一個名為 $1
的欄位,這也是另一個位置參數的名稱。
var r = (2, $1: 1);
以下程式碼會產生此診斷訊息,因為記錄類型註解具有一個名為 $1
的欄位,這也是另一個位置參數的名稱。
void f((int, String, {int $1}) r) {}
常見修正方式
#重新命名欄位。
var r = (a: 1, d: 4);
struct中無效的欄位類型
#結構類別中的欄位不能具有類型 '{0}'。它們只能宣告為 'int'、'double'、'Array'、'Pointer' 或 'Struct' 或 'Union' 的子類型。
描述
#當 Struct
的子類別中的欄位具有類型,而不是 int
、double
、Array
、Pointer
或 Struct
或 Union
的子類型時,分析器會產生此診斷訊息。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼會產生此診斷訊息,因為欄位 str
具有類型 String
,這不是 Struct
子類別中欄位的允許類型之一。
import 'dart:ffi';
final class C extends Struct {
external String s;
@Int32()
external int i;
}
常見修正方式
#對欄位使用允許的類型之一。
import 'dart:ffi';
import 'package:ffi/ffi.dart';
final class C extends Struct {
external Pointer<Utf8> s;
@Int32()
external int i;
}
無效的實作覆寫
#'{1}.{0}' ('{2}') 不是 '{3}.{0}' ('{4}') 的有效具體實作。
Setter '{1}.{0}' ('{2}') 不是 '{3}.{0}' ('{4}') 的有效具體實作。
描述
#當以下所有條件都成立時,分析器會產生此診斷訊息:
- 一個類別定義了一個抽象成員。
- 在超類別中存在該成員的具體實作。
- 具體實作不是抽象方法的有效實作。
具體實作可能是無效的,因為回傳類型、方法參數的類型或型別參數不相容。
範例
#以下程式碼會產生此診斷訊息,因為方法 A.add
具有類型為 int
的參數,而覆寫方法 B.add
具有對應的類型為 num
的參數。
class A {
int add(int a) => a;
}
class B extends A {
int add(num a);
}
這是一個問題,因為在像以下這樣的 B.add
調用中:
void f(B b) {
b.add(3.4);
}
B.add
期望能夠接受,例如,一個 double
,但是當方法 A.add
被執行時(因為它是 add
的唯一具體實作),將會拋出運行時異常,因為 double
無法指派給類型為 int
的參數。
常見修正方式
#如果子類別中的方法可以符合超類別中的實作,則更改子類別中的宣告(如果相同,則移除它)。
class A {
int add(int a) => a;
}
class B extends A {
int add(int a);
}
如果可以將超類別中的方法廣義化,使其成為子類別中方法的有效實作,則更改超類別方法。
class A {
int add(num a) => a.floor();
}
class B extends A {
int add(num a);
}
如果超類別中的方法和子類別中的方法都無法更改,則在子類別中提供方法的具體實作。
class A {
int add(int a) => a;
}
class B extends A {
int add(num a) => a.floor();
}
無效的內嵌函式類型
#內聯函數類型不能用於泛型函數類型中的參數。
描述
#當泛型函數類型具有一個函數值參數,該參數是使用較舊的內聯函數類型語法編寫時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為在用於定義 F
的泛型函數類型中,參數 f
使用了內聯函數類型語法。
typedef F = int Function(int f(String s));
常見修正方式
#對參數的類型使用泛型函數語法。
typedef F = int Function(int Function(String));
無效的內部註解
#只有套件私有 API 中的公有元素才能標記為內部。
描述
#當宣告標記有 internal
註解,且該宣告位於公有程式庫中或具有私有名稱時,分析器會產生此診斷訊息。
範例
#當在公有程式庫中時,以下程式碼會產生此診斷訊息,因為 internal
註解不能應用於公有程式庫中的宣告。
import 'package:meta/meta.dart';
@internal
class C {}
無論是在公有程式庫還是內部程式庫中,以下程式碼都會產生此診斷訊息,因為 internal
註解不能應用於具有私有名稱的宣告。
import 'package:meta/meta.dart';
@internal
class _C {}
void f(_C c) {}
常見修正方式
#如果宣告具有私有名稱,則移除註解。
class _C {}
void f(_C c) {}
如果宣告具有公有名稱並且打算在套件內部使用,則將帶註解的宣告移至內部程式庫(換句話說,src
目錄內的程式庫)。
否則,移除註解的使用。
class C {}
無效的語言版本覆寫
#Dart 語言版本覆寫註解後面不能跟隨任何非空白字元。
Dart 語言版本覆寫註解必須使用版本號碼指定,例如 '=' 字元後的 '2.0'。
Dart 語言版本覆寫註解必須使用 '=' 字元指定。
Dart 語言版本覆寫註解必須使用正好兩個斜線指定。
Dart 語言版本覆寫註解必須使用全小寫的單字 'dart' 指定。
Dart 語言版本覆寫號碼不能以字母作為前綴。
Dart 語言版本覆寫號碼必須以 '@dart' 開頭。
語言版本覆寫不能指定大於最新已知語言版本的版本:{0}.{1}。
語言版本覆寫必須在任何宣告或指令之前指定。
描述
#當一個看起來像是嘗試指定語言版本覆寫的註解不符合此類註解的要求時,分析器會產生此診斷訊息。有關更多資訊,請參閱 每個程式庫的語言版本選擇。
範例
#以下程式碼會產生此診斷訊息,因為單字 dart
在此類註解中必須是小寫,並且因為在單字 dart
和版本號碼之間沒有等號。
// @Dart 2.13
常見修正方式
#如果註解打算作為語言版本覆寫,則更改註解以遵循正確的格式。
// @dart = 2.13
無效的字面值註解
#只有常數建構子才能具有 @literal
註解。
描述
#當 literal
註解應用於常數建構子以外的任何事物時,分析器會產生此診斷訊息。
範例
#下列程式碼會產生此診斷訊息,因為建構子不是 const
建構子
import 'package:meta/meta.dart';
class C {
@literal
C();
}
以下程式碼會產生此診斷訊息,因為 x
不是建構子。
import 'package:meta/meta.dart';
@literal
var x;
常見修正方式
#如果註解在建構子上,且建構子應盡可能始終使用 const
調用,則使用 const
關鍵字標記建構子。
import 'package:meta/meta.dart';
class C {
@literal
const C();
}
如果建構子不能標記為 const
,則移除註解。
如果註解在建構子以外的任何事物上,則移除註解。
var x;
建構子上無效的修飾詞
#修飾詞 '{0}' 不能應用於建構子的主體。
描述
#當建構子的主體以以下修飾詞之一作為前綴時,分析器會產生此診斷訊息:async
、async*
或 sync*
。建構子主體必須是同步的。
範例
#以下程式碼會產生此診斷訊息,因為 C
的建構子的主體被標記為 async
。
class C {
C() async {}
}
常見修正方式
#如果建構子可以是同步的,則移除修飾詞。
class C {
C();
}
如果建構子不能是同步的,則使用靜態方法來建立實例。
class C {
C();
static Future<C> c() async {
return C();
}
}
setter上無效的修飾詞
#Setter 不能使用 'async'、'async*' 或 'sync*'。
描述
#當 setter 的主體以以下修飾詞之一作為前綴時,分析器會產生此診斷訊息:async
、async*
或 sync*
。Setter 主體必須是同步的。
範例
#以下程式碼產生此診斷訊息,因為 setter x
的主體被標記為 async
class C {
set x(int i) async {}
}
常見修正方式
#如果 setter 可以是同步的,請移除修飾詞
class C {
set x(int i) {}
}
如果 setter 無法是同步的,請改用方法來設定值
class C {
void x(int i) async {}
}
無效的非虛擬註解
#@nonVirtual
註解只能套用至具體的實例成員。
描述
#當在類別、Mixin 或列舉的成員以外的宣告中,或是成員不是具體的實例成員時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為註解是在類別宣告上,而不是在類別內部的成員上
import 'package:meta/meta.dart';
@nonVirtual
class C {}
以下程式碼產生此診斷訊息,因為方法 m
是一個抽象方法
import 'package:meta/meta.dart';
abstract class C {
@nonVirtual
void m();
}
以下程式碼產生此診斷訊息,因為方法 m
是一個靜態方法
import 'package:meta/meta.dart';
abstract class C {
@nonVirtual
static void m() {}
}
常見修正方式
#如果宣告不是類別、Mixin 或列舉的成員,請移除註解
class C {}
如果成員的目的是成為具體的實例成員,請使其成為具體的實例成員
import 'package:meta/meta.dart';
abstract class C {
@nonVirtual
void m() {}
}
如果成員的意圖不是成為具體的實例成員,請移除註解
abstract class C {
static void m() {}
}
無效的_null_感知運算子
#元素不能為 null,因此 null 感知運算子 '?' 是不必要的。
Map 條目的鍵不能為 null,因此 null 感知運算子 '?' 是不必要的。
Map 條目的值不能為 null,因此 null 感知運算子 '?' 是不必要的。
由於短路求值,接收器不能為 'null',因此不能使用 null 感知運算子 '{0}'。
接收器不能為 null,因此 null 感知運算子 '{0}' 是不必要的。
描述
#當在已知為不可為 null 的接收器上使用 null 感知運算子 (?.
、?..
、?[
、?..[
或 ...?
) 時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 s
不能為 null
int? getLength(String s) {
return s?.length;
}
以下程式碼產生此診斷訊息,因為 a
不能為 null
var a = [];
var b = [...?a];
以下程式碼產生此診斷訊息,因為 s?.length
不能傳回 null
void f(String? s) {
s?.length?.isEven;
}
s?.length
不能傳回 null
的原因是,如果 s
為 null
,則在 s
之後的 null 感知運算子會短路求值 length
和 isEven
。換句話說,如果 s
為 null
,則 length
和 isEven
都將不會被調用;如果 s
為非 null
,則 length
不能傳回 null
值。無論如何,isEven
都不能在 null
值上調用,因此 null 感知運算子是不必要的。請參閱 Understanding null safety 以取得更多詳細資訊。
以下程式碼產生此診斷訊息,因為 s
不能為 null
。
void f(Object? o) {
var s = o as String;
s?.length;
}
儘管 o
可以為 null
,但 s
不能為 null 的原因是強制轉換為 String
,這是一個不可為 null 的類型。如果 o
的值為 null
,則強制轉換將會失敗,並且 length
的調用將不會發生。
以下程式碼產生此診斷訊息,因為 s
不能為 null
List<String> makeSingletonList(String s) {
return <String>[?s];
}
常見修正方式
#將 null 感知運算子替換為非 null 感知等效項;例如,將 ?.
變更為 .
int getLength(String s) {
return s.length;
}
(請注意,傳回類型也已變更為不可為 null,這在某些情況下可能不合適。)
無效的覆寫
#'{1}.{0}' ('{2}') 不是 '{3}.{0}' ('{4}') 的有效覆寫。
Setter '{1}.{0}' ('{2}') 不是 '{3}.{0}' ('{4}') 的有效覆寫。
描述
#當在類別中找到成員覆寫了超類型的成員,且覆寫無效時,分析器會產生此診斷訊息。如果以下所有條件都成立,則覆寫有效
- 它允許被覆寫成員所允許的所有引數。
- 它不要求任何被覆寫成員未要求的引數。
- 被覆寫成員的每個參數的類型都可指派給覆寫的對應參數。
- 覆寫的傳回類型可指派給被覆寫成員的傳回類型。
範例
#以下程式碼產生此診斷訊息,因為參數 s
(String
) 的類型不可指派給參數 i
(int
) 的類型
class A {
void m(int i) {}
}
class B extends A {
void m(String s) {}
}
常見修正方式
#如果無效方法的目的是覆寫超類別中的方法,請變更它以符合規範
class A {
void m(int i) {}
}
class B extends A {
void m(int i) {}
}
如果它的目的不是覆寫超類別中的方法,請重新命名它
class A {
void m(int i) {}
}
class B extends A {
void m2(String s) {}
}
無效的非虛擬成員覆寫
#成員 '{0}' 在 '{1}' 中宣告為 non-virtual,且無法在子類別中覆寫。
描述
#當類別、Mixin 或列舉的成員覆寫了具有 @nonVirtual
註解的成員時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 B
中的方法 m
覆寫了 A
中的方法 m
,而 A
中的方法 m
使用了 @nonVirtual
註解
import 'package:meta/meta.dart';
class A {
@nonVirtual
void m() {}
}
class B extends A {
@override
void m() {}
}
常見修正方式
#如果超類別中方法的註解是正確的 (超類別中的方法不應被覆寫),則移除或重新命名覆寫方法
import 'package:meta/meta.dart';
class A {
@nonVirtual
void m() {}
}
class B extends A {}
如果超類別中的方法旨在被覆寫,則移除 @nonVirtual
註解
class A {
void m() {}
}
class B extends A {
@override
void m() {}
}
共用_case_範圍中無效的模式變數
#變數 '{0}' 在共用此主體的所有情況下,不具有相同的類型和/或最終性。
變數 '{0}' 在某些情況下可用,但在共用此主體的所有情況下並非都可用。
變數 '{0}' 不可用,因為存在標籤或 'default' case。
描述
#當 switch 陳述式中的多個 case 子句共用一個主體,且至少其中一個子句宣告了一個在共用陳述式中被引用的變數,但該變數並非在所有 case 子句中都宣告,或是在宣告方式上不一致時,分析器會產生此診斷訊息。
如果變數未在所有 case 子句中宣告,則如果未宣告變數的子句是符合且執行主體的子句之一,則它將沒有值。這包括其中一個 case 子句是 default
子句的情況。
如果變數的宣告方式不一致,在某些情況下是 final
而在其他情況下不是 final
,或者在不同情況下具有不同的類型,則變數的類型或最終性的語意應為何是未定義的。
範例
#以下程式碼產生此診斷訊息,因為變數 a
僅在其中一個 case 子句中宣告,如果在第二個子句符合 x
時,將沒有值
void f(Object? x) {
switch (x) {
case int a when a > 0:
case 0:
a;
}
}
以下程式碼產生此診斷訊息,因為變數 a
未在 default
子句中宣告,如果在沒有其他子句符合 x
的情況下執行主體,將沒有值
void f(Object? x) {
switch (x) {
case int a when a > 0:
default:
a;
}
}
以下程式碼產生此診斷訊息,因為如果在不同的 case 群組導致控制權在標籤處繼續時,變數 a
將沒有值
void f(Object? x) {
switch (x) {
someLabel:
case int a when a > 0:
a;
case int b when b < 0:
continue someLabel;
}
}
以下程式碼產生此診斷訊息,因為變數 a
雖然在所有 case 子句中都已指派值,但在每個子句中都不具有相同的關聯類型
void f(Object? x) {
switch (x) {
case int a when a < 0:
case num a when a > 0:
a;
}
}
以下程式碼產生此診斷訊息,因為變數 a
在第一個 case 子句中是 final
,但在第二個 case 子句中不是 final
void f(Object? x) {
switch (x) {
case final int a when a < 0:
case int a when a > 0:
a;
}
}
常見修正方式
#如果變數未在所有 case 中宣告,且您需要在陳述式中引用它,則在其他 case 中宣告它
void f(Object? x) {
switch (x) {
case int a when a > 0:
case int a when a == 0:
a;
}
}
如果變數未在所有 case 中宣告,且您不需要在陳述式中引用它,則移除對它的引用,並從其他 case 中移除宣告
void f(int x) {
switch (x) {
case > 0:
case 0:
}
}
如果變數的類型不同,請決定變數應具有的類型,並使 case 保持一致
void f(Object? x) {
switch (x) {
case num a when a < 0:
case num a when a > 0:
a;
}
}
如果變數的最終性不同,請決定它應該是 final
或非 final
,並使情況保持一致。
void f(Object? x) {
switch (x) {
case final int a when a < 0:
case final int a when a > 0:
a;
}
}
無效的平台欄位
#'platforms' 欄位必須是一個以平台作為鍵的 Map。
描述
#當指定了頂層 platforms
欄位,但其值不是帶有鍵的 Map 時,分析器會產生此診斷訊息。若要深入了解如何指定套件支援的平台,請查看 平台宣告的文件。
範例
#以下 pubspec.yaml
產生此診斷訊息,因為 platforms
應為 Map。
name: example
platforms:
- android
- web
- ios
常見修正方式
#如果您可以依賴自動平台偵測,則省略頂層 platforms
欄位。
name: example
如果您需要手動指定支援平台的清單,則將 platforms
欄位寫為以平台名稱作為鍵的 Map。
name: example
platforms:
android:
web:
ios:
對產生器列舉建構子的無效參考
#產生器列舉建構子只能用作重新導向的目標。
描述
#當在列舉中定義的產生器建構子用於建立其中一個列舉常數以外的任何地方,或用作來自相同列舉中另一個建構子的重新導向目標時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 E
的建構子正被用於在函數 f
中建立實例
enum E {
a(0);
const E(int x);
}
E f() => const E(2);
常見修正方式
#如果存在具有相同值的列舉值,或者如果您新增了這樣的常數,則直接引用該常數
enum E {
a(0), b(2);
const E(int x);
}
E f() => E.b;
如果您需要使用建構子調用,則使用工廠建構子
enum E {
a(0);
const E(int x);
factory E.c(int x) => a;
}
E f() => E.c(2);
對_this的無效參考
#無效的 'this' 表達式參考。
描述
#當在實例方法或產生器建構子之外使用 this
時,分析器會產生此診斷訊息。保留字 this
僅在實例方法、產生器建構子或延遲實例欄位宣告的初始化器的上下文中定義。
範例
#以下程式碼產生此診斷訊息,因為 v
是一個頂層變數
C f() => this;
class C {}
常見修正方式
#使用適當類型的變數來取代 this
,必要時宣告它
C f(C c) => c;
class C {}
catchError的無效傳回類型
#類型為 '{0}' 的值無法由 'onError' 處理常式傳回,因為它必須可指派給 '{1}'。
傳回類型 '{0}' 不可指派給 '{1}',這是 'Future.catchError' 所要求的。
描述
#當 Future.catchError
的調用具有一個引數,其傳回類型與 Future
實例傳回的類型不相容時,分析器會產生此診斷訊息。在執行階段,方法 catchError
嘗試從回呼傳回值作為 future 的結果,這會導致另一個例外被拋出。
範例
#以下程式碼產生此診斷訊息,因為 future
被宣告為傳回 int
,而 callback
被宣告為傳回 String
,且 String
不是 int
的子類型
void f(Future<int> future, String Function(dynamic, StackTrace) callback) {
future.catchError(callback);
}
以下程式碼產生此診斷訊息,因為傳遞給 catchError
的閉包傳回 int
,而 future
被宣告為傳回 String
void f(Future<String> future) {
future.catchError((error, stackTrace) => 3);
}
常見修正方式
#如果 Future
的實例宣告正確,則變更回呼以符合
void f(Future<int> future, int Function(dynamic, StackTrace) callback) {
future.catchError(callback);
}
如果 Future
的實例宣告錯誤,則變更它以符合回呼
void f(Future<String> future, String Function(dynamic, StackTrace) callback) {
future.catchError(callback);
}
無效的_sealed_註解
#@sealed
註解只能套用至類別。
描述
#當類別宣告以外的宣告具有 @sealed
註解時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 @sealed
註解是在方法宣告上
import 'package:meta/meta.dart';
class A {
@sealed
void m() {}
}
常見修正方式
#移除註解
class A {
void m() {}
}
無效的_super_形式參數位置
#Super 參數只能在非重新導向的產生器建構子中使用。
描述
#當 super 參數用於非重新導向的產生器建構子以外的任何地方時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 super 參數 x
在重新導向的產生器建構子中
class A {
A(int x);
}
class B extends A {
B.b(super.x) : this._();
B._() : super(0);
}
以下程式碼產生此診斷訊息,因為 super 參數 x
不在產生器建構子中
class A {
A(int x);
}
class C extends A {
factory C.c(super.x) => C._();
C._() : super(0);
}
以下程式碼產生此診斷訊息,因為 super 參數 x
在方法中
class A {
A(int x);
}
class D extends A {
D() : super(0);
void m(super.x) {}
}
常見修正方式
#如果包含 super 參數的函數可以變更為非重新導向的產生器建構子,請執行此操作
class A {
A(int x);
}
class B extends A {
B.b(super.x);
}
如果包含 super 參數的函數無法變更為非重新導向的產生器建構子,則移除 super
class A {
A(int x);
}
class D extends A {
D() : super(0);
void m(int x) {}
}
const_字面值中無效的類型引數
#常數 List 字面值不能在類型引數中使用類型參數,例如 '{0}'。
常數 Map 字面值不能在類型引數中使用類型參數,例如 '{0}'。
常數 Set 字面值不能在類型引數中使用類型參數,例如 '{0}'。
描述
#當類型參數用於以 const
為前綴的 List、Map 或 Set 字面值中的類型引數時,分析器會產生此診斷訊息。這是不允許的,因為類型參數的值 (將在執行階段使用的實際類型) 在編譯時無法得知。
範例
#以下程式碼產生此診斷訊息,因為類型參數 T
在建立常數 List 時被用作類型引數
List<T> newList<T>() => const <T>[];
以下程式碼產生此診斷訊息,因為類型參數 T
在建立常數 Map 時被用作類型引數
Map<String, T> newSet<T>() => const <String, T>{};
以下程式碼產生此診斷訊息,因為類型參數 T
在建立常數 Set 時被用作類型引數
Set<T> newSet<T>() => const <T>{};
常見修正方式
#如果將用於類型參數的類型可以在編譯時得知,則移除類型參數
List<int> newList() => const <int>[];
如果將用於類型參數的類型在執行階段之前無法得知,則移除關鍵字 const
List<T> newList<T>() => <T>[];
無效的_URI
#無效的 URI 語法:'{0}'。
描述
#當指令中的 URI 不符合有效 URI 的語法時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 '#'
不是有效的 URI
import '#';
常見修正方式
#將無效的 URI 替換為有效的 URI。
在擴充功能中無效地使用_covariant
#Extension 中不能有修飾詞 '{0}'。
描述
#當在 extension 內部宣告的成員在參數宣告中使用關鍵字 covariant
時,分析器會產生此診斷訊息。Extension 不是類別,也沒有子類別,因此該關鍵字沒有任何作用。
範例
#以下程式碼產生此診斷訊息,因為 i
被標記為 covariant
extension E on String {
void a(covariant int i) {}
}
常見修正方式
#移除 covariant
關鍵字
extension E on String {
void a(int i) {}
}
無效地使用內部成員
#成員 '{0}' 只能在其套件內使用。
描述
#當在包含宣告的套件外部找到對使用 internal
註解標記的宣告的引用時,分析器會產生此診斷訊息。
範例
#假設一個套件 p
定義了一個程式庫,其中包含一個使用 internal
註解標記的宣告
import 'package:meta/meta.dart';
@internal
class C {}
以下程式碼產生此診斷訊息,因為它正在引用類別 C
,該類別不應在套件 p
外部使用
import 'package:p/src/p.dart';
void f(C c) {}
常見修正方式
#移除對內部宣告的引用。
無效地使用_null值
#值始終為 'null' 的表達式無法被取值 (dereferenced)。
描述
#當值將始終為 null
的表達式被取值時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 x
將始終為 null
int f(Null x) {
return x.length;
}
常見修正方式
#如果值允許為 null
以外的其他值,則變更表達式的類型
int f(String? x) {
return x!.length;
}
在程式庫外部無效地使用類型
#類別 '{0}' 無法在其程式庫外部擴展,因為它是一個 final 類別。
類別 '{0}' 無法在其程式庫外部擴展,因為它是一個 interface 類別。
類別 '{0}' 無法在其程式庫外部擴展、實作或混入,因為它是一個 sealed 類別。
類別 '{0}' 無法在其程式庫外部實作,因為它是一個 base 類別。
類別 '{0}' 無法在其程式庫外部實作,因為它是一個 final 類別。
類別 '{0}' 無法在其程式庫外部用作 Mixin 超類別約束,因為它是一個 final 類別。
Mixin '{0}' 無法在其程式庫外部實作,因為它是一個 base Mixin。
描述
#當 extends
、implements
、with
或 on
子句以不允許的方式使用類別或 Mixin,並考慮到該類別或 Mixin 宣告上的修飾詞時,分析器會產生此診斷訊息。
訊息指定了宣告的使用方式以及為何不允許。
範例
#假設一個檔案 a.dart
定義了一個 base 類別 A
base class A {}
以下程式碼產生此診斷訊息,因為類別 B
實作了類別 A
,但 base
修飾詞阻止了 A
在定義它的程式庫外部被實作
import 'a.dart';
final class B implements A {}
常見修正方式
#此類型的使用在其宣告程式庫外部受到限制。如果存在另一個可提供類似功能且不受限制的類型,請替換該類型
class B implements C {}
class C {}
如果沒有其他合適的類型,則移除該類型,並可能移除整個子句
class B {}
無效地使用可見以進行覆寫的成員
#成員 '{0}' 只能用於覆寫。
描述
#當在宣告它的程式庫外部引用以 visibleForOverriding
註解標記的實例成員,且原因不是為了覆寫它時,分析器會產生此診斷訊息。
範例
#假設一個檔案 a.dart
包含以下宣告
import 'package:meta/meta.dart';
class A {
@visibleForOverriding
void a() {}
}
以下程式碼產生此診斷訊息,因為方法 m
正在被調用,即使它公開的唯一原因是允許它被覆寫
import 'a.dart';
class B extends A {
void b() {
a();
}
}
常見修正方式
#移除成員的無效使用。
無效地使用可見以進行測試的成員
#成員 '{0}' 只能在 '{1}' 或測試中使用。
描述
#當在宣告它的程式庫或 test
目錄中的程式庫以外的任何地方引用以 @visibleForTesting
註解標記的成員時,分析器會產生此診斷訊息。
範例
#假設一個檔案 c.dart
包含以下內容
import 'package:meta/meta.dart';
class C {
@visibleForTesting
void m() {}
}
以下程式碼在不在 test
目錄中時產生此診斷訊息,因為方法 m
被標記為僅對測試可見
import 'c.dart';
void f(C c) {
c.m();
}
常見修正方式
#如果註解的成員不應在測試外部引用,則移除引用
import 'c.dart';
void f(C c) {}
如果可以在測試外部引用註解的成員,則移除註解
class C {
void m() {}
}
無效的可見性註解
#成員 '{0}' 使用 '{1}' 註解,但此註解僅對公開成員的宣告有意義。
描述
#當 visibleForTemplate
或 visibleForTesting
註解套用至非公開宣告時,分析器會產生此診斷訊息。
範例
#下列程式碼會產生此診斷訊息
import 'package:meta/meta.dart';
@visibleForTesting
void _someFunction() {}
void f() => _someFunction();
常見修正方式
#如果宣告不需要被測試程式碼使用,則移除註解
void _someFunction() {}
void f() => _someFunction();
如果需要,則使其公開
import 'package:meta/meta.dart';
@visibleForTesting
void someFunction() {}
void f() => someFunction();
無效的可見以進行覆寫的註解
#visibleForOverriding
註解只能套用至可以被覆寫的公開實例成員。
描述
#當類別的公開實例成員以外的任何內容使用 visibleForOverriding
進行註解時,分析器會產生此診斷訊息。由於只有公開實例成員可以在定義程式庫外部被覆寫,因此註解任何其他宣告沒有任何價值。
範例
#以下程式碼產生此診斷訊息,因為註解是在類別上,而類別無法被覆寫
import 'package:meta/meta.dart';
@visibleForOverriding
class C {}
常見修正方式
#移除註解
class C {}
無效的可見於範本外部的註解
#visibleOutsideTemplate
註解只能套用至使用 visibleForTemplate
註解標記的類別、列舉或 Mixin 的成員。
描述
#當 @visibleOutsideTemplate
註解被錯誤使用時,分析器會產生此診斷訊息。此註解僅用於註解具有 @visibleForTemplate
註解的類別、列舉或 Mixin 的成員,以使這些成員選擇退出 @visibleForTemplate
強加的可見性限制。
範例
#以下程式碼產生此診斷訊息,因為在類別層級沒有 @visibleForTemplate
註解
import 'package:angular_meta/angular_meta.dart';
class C {
@visibleOutsideTemplate
int m() {
return 1;
}
}
以下程式碼產生此診斷訊息,因為註解是在類別宣告上,而不是類別、列舉或 Mixin 的成員上
import 'package:angular_meta/angular_meta.dart';
@visibleOutsideTemplate
class C {}
常見修正方式
#如果類別僅可見以便模板可以引用它,則將 @visibleForTemplate
註解新增至類別
import 'package:angular_meta/angular_meta.dart';
@visibleForTemplate
class C {
@visibleOutsideTemplate
int m() {
return 1;
}
}
如果 @visibleOutsideTemplate
註解在任何不是具有 @visibleForTemplate
註解的類別、列舉或 Mixin 的成員上,則移除註解
class C {}
沒有呼叫的擴充功能調用
#Extension '{0}' 未定義 'call' 方法,因此覆寫不能用於調用中。
描述
#當 extension 覆寫用於調用函數,但 extension 未宣告 call
方法時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 extension E
未定義 call
方法
extension E on String {}
void f() {
E('')();
}
常見修正方式
#如果 extension 的目的是定義 call
方法,則宣告它
extension E on String {
int call() => 0;
}
void f() {
E('')();
}
如果擴展類型定義了 call
方法,則移除 extension 覆寫。
如果未定義 call
方法,則重寫程式碼使其不調用 call
方法。
非函式的調用
#'{0}' 不是函數。
描述
#當分析器找到函數調用,但被調用函數的名稱被定義為函數以外的其他內容時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 Binary
是函數類型的名稱,而不是函數
typedef Binary = int Function(int, int);
int f() {
return Binary(1, 2);
}
常見修正方式
#將名稱替換為函數的名稱。
非函式運算式的調用
#表達式未求值為函數,因此無法調用它。
描述
#當找到函數調用,但被引用的名稱不是函數的名稱,或者當計算函數的表達式未計算出函數時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 x
不是函數
int x = 0;
int f() => x;
var y = x();
以下程式碼產生此診斷訊息,因為 f()
未傳回函數
int x = 0;
int f() => x;
var y = f()();
常見修正方式
#如果您需要調用函數,則將引數列表之前的程式碼替換為函數的名稱或計算函數的表達式
int x = 0;
int f() => x;
var y = f();
外部範圍中的標籤
#無法引用在外層方法中宣告的標籤 '{0}'。
描述
#當 break
或 continue
陳述式引用在包含 break
或 continue
陳述式出現的函數的函數或方法中宣告的標籤時,分析器會產生此診斷訊息。break
和 continue
陳述式不能用於將控制權轉移到包含它們的函數外部。
範例
#以下程式碼產生此診斷訊息,因為標籤 loop
在本機函數 g
外部宣告
void f() {
loop:
while (true) {
void g() {
break loop;
}
g();
}
}
常見修正方式
#嘗試重寫程式碼,使其不必將控制權轉移到本機函數外部,可能通過內聯本機函數
void f() {
loop:
while (true) {
break loop;
}
}
如果這不可能,則嘗試重寫本機函數,以便可以使用函數傳回的值來確定是否轉移控制權
void f() {
loop:
while (true) {
bool g() {
return true;
}
if (g()) {
break loop;
}
}
}
未定義的標籤
#無法引用未定義的標籤 '{0}'。
描述
#當分析器發現對未在引用它的 break
或 continue
陳述式的範圍內定義的標籤的引用時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為標籤 loop
在任何地方都未定義
void f() {
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if (j != 0) {
break loop;
}
}
}
}
常見修正方式
#如果標籤應位於最內層的封閉 do
、for
、switch
或 while
陳述式上,則移除標籤
void f() {
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if (j != 0) {
break;
}
}
}
}
如果標籤應位於其他某些陳述式上,則新增標籤
void f() {
loop: for (int i = 0; i < 10; i++) {
for (int j = 0; j < 10; j++) {
if (j != 0) {
break loop;
}
}
}
}
具有_const_建構子的_late_final_欄位
#具有產生器 const 建構子的類別中不能有 late final 欄位。
描述
#當具有至少一個 const
建構子的類別也具有標記為 late
和 final
的欄位時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為類別 A
具有 const
建構子,且 final
欄位 f
被標記為 late
class A {
late final int f;
const A();
}
常見修正方式
#如果欄位不需要標記為 late
,則從欄位中移除 late
修飾詞
class A {
final int f = 0;
const A();
}
如果欄位必須標記為 late
,則從建構子中移除 const
修飾詞
class A {
late final int f;
A();
}
已賦值的_late_final_區域變數
#late final 本機變數已指派值。
描述
#當分析器可以證明標記為 late
和 final
的本機變數在另一個指派發生時已經被指派了一個值時,分析器會產生此診斷訊息。
由於 final
變數只能指派一次,因此後續的指派保證會失敗,因此會被標記。
範例
#以下程式碼產生此診斷訊息,因為 final
變數 v
在兩個地方被指派了值
int f() {
late final int v;
v = 0;
v += 1;
return v;
}
常見修正方式
#如果您需要能夠重新指派變數,則移除 final
關鍵字
int f() {
late int v;
v = 0;
v += 1;
return v;
}
如果您不需要重新指派變數,則移除除第一個指派以外的所有指派
int f() {
late final int v;
v = 0;
return v;
}
leaf_呼叫不得傳回控制代碼
#FFI 葉節點呼叫不能傳回 'Handle'。
描述
#當 Pointer.asFunction
或 DynamicLibrary.lookupFunction
的調用中 isLeaf
引數的值為 true
,且將傳回的函數將具有 Handle
的傳回類型時,分析器會產生此診斷訊息。
當 Native
註解中的 isLeaf
引數的值為 true
,且註解上的類型引數是傳回類型為 Handle
的函數類型時,分析器也會產生此診斷訊息。
在所有這些情況下,葉節點呼叫僅支援類型 bool
、int
、float
、double
,以及作為傳回類型 void
。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼產生此診斷訊息,因為函數 p
傳回 Handle
,但 isLeaf
引數為 true
import 'dart:ffi';
void f(Pointer<NativeFunction<Handle Function()>> p) {
p.asFunction<Object Function()>(isLeaf: true);
}
常見修正方式
#如果函數傳回 handle,則移除 isLeaf
引數
import 'dart:ffi';
void f(Pointer<NativeFunction<Handle Function()>> p) {
p.asFunction<Object Function()>();
}
如果函數傳回支援的類型之一,則更正類型資訊
import 'dart:ffi';
void f(Pointer<NativeFunction<Int32 Function()>> p) {
p.asFunction<int Function()>(isLeaf: true);
}
leaf_呼叫不得採用控制代碼
#FFI 葉節點呼叫不能接受類型為 'Handle' 的引數。
描述
#當 Pointer.asFunction
或 DynamicLibrary.lookupFunction
的調用中 isLeaf
引數的值為 true
,且將傳回的函數將具有類型為 Handle
的參數時,分析器會產生此診斷訊息。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼產生此診斷訊息,因為函數 p
具有類型為 Handle
的參數,但 isLeaf
引數為 true
import 'dart:ffi';
void f(Pointer<NativeFunction<Void Function(Handle)>> p) {
p.asFunction<void Function(Object)>(isLeaf: true);
}
常見修正方式
#如果函數具有至少一個類型為 Handle
的參數,則移除 isLeaf
引數
import 'dart:ffi';
void f(Pointer<NativeFunction<Void Function(Handle)>> p) {
p.asFunction<void Function(Object)>();
}
如果函數的參數都不是 Handle
,則更正類型資訊
import 'dart:ffi';
void f(Pointer<NativeFunction<Void Function(Int8)>> p) {
p.asFunction<void Function(int)>(isLeaf: true);
}
清單元素類型不可賦值
#元素類型 '{0}' 無法指派給 List 類型 '{1}'。
描述
#當 List 字面值中元素的類型不可指派給 List 的元素類型時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 2.5
是一個 double,而 List 只能容納整數
List<int> x = [1, 2.5, 3];
常見修正方式
#如果您打算將不同的物件新增到 List,則將元素替換為計算預期物件的表達式
List<int> x = [1, 2, 3];
如果物件不應在 List 中,則移除元素
List<int> x = [1, 3];
如果計算的物件是正確的,則擴大 List 的元素類型以允許它需要包含的所有不同類型的物件
List<num> x = [1, 2.5, 3];
main第一個位置參數類型
#'main' 函數的第一個位置參數的類型必須是 'List<String>' 的超類型
描述
#當名為 main
的函數的第一個位置參數不是 List<String>
的超類型時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 List<int>
不是 List<String>
的超類型
void main(List<int> args) {}
常見修正方式
#如果函數是一個進入點,則將第一個位置參數的類型變更為 List<String>
的超類型
void main(List<String> args) {}
如果函數不是一個進入點,則變更函數的名稱
void f(List<int> args) {}
main具有必要的具名參數
#'main' 函數不能有任何必要的具名參數。
描述
#當名為 main
的函數具有一個或多個必要的具名參數時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為名為 main
的函數具有一個必要的具名參數 (x
)
void main({required int x}) {}
常見修正方式
#如果函數是一個進入點,則移除 required
關鍵字
void main({int? x}) {}
如果函數不是一個進入點,則變更函數的名稱
void f({required int x}) {}
main具有過多必要的位置參數
#'main' 函數不能有多於兩個的必要位置參數。
描述
#當名為 main
的函數具有多於兩個的必要位置參數時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為函數 main
具有三個必要的位置參數
void main(List<String> args, int x, int y) {}
常見修正方式
#如果函數是一個進入點,且未使用的額外參數,則移除它們
void main(List<String> args, int x) {}
如果函數是一個進入點,但使用的額外參數用於函數未被用作進入點時,則使額外參數成為可選的
void main(List<String> args, int x, [int y = 0]) {}
如果函數不是一個進入點,則變更函數的名稱
void f(List<String> args, int x, int y) {}
main不是函式
#名為 'main' 的宣告必須是一個函數。
描述
#當程式庫包含名稱為 main
的宣告,但該宣告不是頂層函數的宣告時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為名稱 main
正被用於宣告頂層變數
var main = 3;
常見修正方式
#為宣告使用不同的名稱
var mainIndex = 3;
map中沒有_map_條目
#Map 條目只能在 Map 字面值中使用。
描述
#當在 Set 字面值中找到 Map 條目 (鍵/值對) 時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為字面值具有 Map 條目,即使它是一個 Set 字面值
var collection = <String>{'a' : 'b'};
常見修正方式
#如果您希望集合是一個 Map,則變更程式碼使其成為 Map。在先前的範例中,您可以通過新增另一個類型引數來執行此操作
var collection = <String, String>{'a' : 'b'};
在其他情況下,您可能需要將顯式類型從 Set
變更為 Map
。
如果您希望集合是一個 Set,則移除 Map 條目,如果兩個值都應包含在 Set 中,則可能將冒號替換為逗號
var collection = <String>{'a', 'b'};
map_金鑰類型不可賦值
#元素類型 '{0}' 無法指派給 Map 鍵類型 '{1}'。
描述
#當 Map 字面值中鍵值對的鍵具有的類型不可指派給 Map 的鍵類型時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 2
是一個 int
,但 Map 的鍵必須是 String
var m = <String, String>{2 : 'a'};
常見修正方式
#如果 Map 的類型是正確的,則變更鍵以具有正確的類型
var m = <String, String>{'2' : 'a'};
如果鍵的類型是正確的,則變更 Map 的鍵類型
var m = <int, String>{2 : 'a'};
map_值類型不可賦值
#元素類型 '{0}' 無法指派給 Map 值類型 '{1}'。
描述
#當 Map 字面值中鍵值對的值具有的類型不可指派給 Map 的值類型時,分析器會產生此診斷訊息。
範例
#以下程式碼產生此診斷訊息,因為 2
是一個 int
,但/ Map 的值必須是 String
var m = <String, String>{'a' : 2};
常見修正方式
#如果 Map 的類型是正確的,則變更值以具有正確的類型
var m = <String, String>{'a' : '2'};
如果值的類型是正確的,則變更 Map 的值類型
var m = <String, int>{'a' : 2};
struct_欄位上不符的註解
#註解與欄位的宣告類型不符。
描述
#當 Struct
或 Union
子類別中欄位的註解與欄位的 Dart 類型不符時,分析器會產生此診斷訊息。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼產生此診斷訊息,因為註解 Double
與 Dart 類型 int
不符
import 'dart:ffi';
final class C extends Struct {
@Double()
external int x;
}
常見修正方式
#如果欄位的類型是正確的,則變更註解以符合
import 'dart:ffi';
final class C extends Struct {
@Int32()
external int x;
}
如果註解是正確的,則變更欄位的類型以符合
import 'dart:ffi';
final class C extends Struct {
@Double()
external double x;
}
struct_欄位上遺失的註解
#'{1}' 子類別中類型為 '{0}' 的欄位必須具有指示原生類型的註解。
描述
#當 Struct
或 Union
子類別中類型需要註解的欄位沒有註解時,分析器會產生此診斷訊息。Dart 類型 int
、double
和 Array
用於表示多個 C 類型,而註解指定了欄位表示的相容 C 類型。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼產生此診斷訊息,因為欄位 x
沒有指示整數值底層寬度的註解
import 'dart:ffi';
final class C extends Struct {
external int x;
}
常見修正方式
#將適當的註解新增至欄位
import 'dart:ffi';
final class C extends Struct {
@Int64()
external int x;
}
遺失的_Dart程式庫
#必要的程式庫 '{0}' 遺失。
描述
#當 Dart 或 Flutter SDK 安裝不正確,並因此導致找不到其中一個 dart:
程式庫時,分析器會產生此診斷訊息。
常見修正方式
#重新安裝 Dart 或 Flutter SDK。
參數遺失預設值
#參數 '{0}' 的類型不允許空值,但隱含預設值為 'null'。
使用空值安全機制時,請使用 'required' 關鍵字,而非 '@required' 註解。
描述
#當可選參數(無論是位置參數或具名參數)具有可能非可空類型,且未指定預設值時,分析器會產生此診斷訊息。沒有明確預設值的可選參數,其隱含預設值為 null
。如果參數的類型不允許參數具有 null
值,則隱含預設值會無效。
範例
#以下程式碼會產生此診斷訊息,因為 x
不能為 null
,且未指定非 null
的預設值
void f([int x]) {}
以下程式碼也會產生相同訊息
void g({int x}) {}
常見修正方式
#如果您想使用 null
來表示未提供任何值,則需要將類型設為可空類型
void f([int? x]) {}
void g({int? x}) {}
如果參數不能為空值,則請提供預設值
void f([int x = 1]) {}
void g({int x = 2}) {}
或將參數設為必要參數
void f(int x) {}
void g({required int x}) {}
遺失的相依性
#遺失匯入套件 '{0}' 的依賴項目。
描述
#當原始碼中匯入了某個套件,但該套件未列為匯入套件的依賴項目時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為套件 path
未列為依賴項目,但套件 example
的原始碼中存在包含套件 path
的 import 陳述式
name: example
dependencies:
meta: ^1.0.2
常見修正方式
#將遺失的套件 path
新增至 dependencies
欄位
name: example
dependencies:
meta: ^1.0.2
path: any
switch中遺失的列舉常數
#遺失 '{0}' 的 case 子句。
描述
#當枚舉的 switch
陳述式未包含枚舉中其中一個值的選項時,分析器會產生此診斷訊息。
請注意,null
始終是枚舉的可能值,因此也必須處理。
範例
#以下程式碼會產生此診斷訊息,因為未處理枚舉值 e2
enum E { e1, e2 }
void f(E e) {
switch (e) {
case E.e1:
break;
}
}
常見修正方式
#如果遺失的值有特殊的處理方式,則請為每個遺失的值新增 case
子句
enum E { e1, e2 }
void f(E e) {
switch (e) {
case E.e1:
break;
case E.e2:
break;
}
}
如果應該以相同方式處理遺失的值,則請新增 default
子句
enum E { e1, e2 }
void f(E e) {
switch (e) {
case E.e1:
break;
default:
break;
}
}
遺失的例外值
#當函式的傳回類型既不是 'void'、'Handle' 也不是 'Pointer' 時,方法 {0} 必須具有例外傳回值(第二個引數)。
描述
#當 Pointer.fromFunction
或 NativeCallable.isolateLocal
方法的調用缺少第二個引數(例外傳回值),且調用要傳回的類型既不是 void
、Handle
也不是 Pointer
時,分析器會產生此診斷訊息。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼會產生此診斷訊息,因為 f
傳回的類型預期為 8 位元整數,但對 fromFunction
的呼叫未包含例外傳回引數
import 'dart:ffi';
int f(int i) => i * 2;
void g() {
Pointer.fromFunction<Int8 Function(Int8)>(f);
}
常見修正方式
#新增例外傳回類型
import 'dart:ffi';
int f(int i) => i * 2;
void g() {
Pointer.fromFunction<Int8 Function(Int8)>(f, 0);
}
struct中遺失的欄位類型
#struct 類別中的欄位必須具有明確宣告的 'int'、'double' 或 'Pointer' 類型。
描述
#當 Struct
或 Union
子類別中的欄位沒有類型註解時,分析器會產生此診斷訊息。每個欄位都必須具有明確的類型,且類型必須為 int
、double
、Pointer
或 Struct
或 Union
的子類別。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼會產生此診斷訊息,因為欄位 str
沒有類型註解
import 'dart:ffi';
final class C extends Struct {
external var str;
@Int32()
external int i;
}
常見修正方式
#明確指定欄位的類型
import 'dart:ffi';
import 'package:ffi/ffi.dart';
final class C extends Struct {
external Pointer<Utf8> str;
@Int32()
external int i;
}
遺失的名稱
#'name' 欄位為必要欄位,但遺失了。
描述
#當沒有最上層 name
鍵時,分析器會產生此診斷訊息。 name
鍵提供套件的名稱,這是必要的。
範例
#以下程式碼會產生此診斷訊息,因為套件沒有名稱
dependencies:
meta: ^1.0.2
常見修正方式
#新增最上層鍵 name
,其值為套件的名稱
name: example
dependencies:
meta: ^1.0.2
遺失的具名模式欄位名稱
#Getter 名稱未明確指定,且模式不是變數。
描述
#當在物件模式中,屬性的規格和用於比對屬性值的模式,兩者皆不具備下列其中一項時,分析器會產生此診斷訊息:
- 冒號前的 getter 名稱
- 可從中推斷 getter 名稱的變數模式
範例
#以下程式碼會產生此診斷訊息,因為在物件模式 (C(:0)
) 中,冒號前沒有 getter 名稱,且冒號後也沒有變數模式
abstract class C {
int get f;
}
void f(C c) {
switch (c) {
case C(:0):
break;
}
}
常見修正方式
#如果您需要在模式的範圍內使用屬性的實際值,則請新增變數模式,其中變數的名稱與要比對的屬性名稱相同
abstract class C {
int get f;
}
void f(C c) {
switch (c) {
case C(:var f) when f == 0:
print(f);
}
}
如果您不需要在模式的範圍內使用屬性的實際值,則請在冒號前新增要比對的屬性名稱
abstract class C {
int get f;
}
void f(C c) {
switch (c) {
case C(f: 0):
break;
}
}
遺失必須覆寫的覆寫
#遺失 '{0}' 的具體實作。
遺失 '{0}' 和 '{1}' 的具體實作。
遺失 '{0}'、'{1}' 和其他 {2} 個的具體實作。
描述
#當具有 @mustBeOverridden
註解的實例成員未在子類別中覆寫時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為當 A.m
標註了 @mustBeOverridden
時,類別 B
沒有繼承方法 A.m
的覆寫
import 'package:meta/meta.dart';
class A {
@mustBeOverridden
void m() {}
}
class B extends A {}
常見修正方式
#如果註解適用於成員,則請在子類別中覆寫成員
import 'package:meta/meta.dart';
class A {
@mustBeOverridden
void m() {}
}
class B extends A {
@override
void m() {}
}
如果註解不適用於成員,則請移除註解
class A {
void m() {}
}
class B extends A {}
遺失的必要引數
#具名參數 '{0}' 為必要參數,但沒有對應的引數。
描述
#當函式的調用遺失了必要的具名參數時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 f
的調用未包含必要具名參數 end
的值
void f(int start, {required int end}) {}
void g() {
f(3);
}
常見修正方式
#新增對應於遺失的必要參數的具名引數
void f(int start, {required int end}) {}
void g() {
f(3, end: 5);
}
遺失的必要參數
#參數 '{0}' 為必要參數。
參數 '{0}' 為必要參數。{1}。
描述
#當調用具有標註為必要的具名參數的方法或函式,但未提供參數的值時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為具名參數 x
為必要參數
import 'package:meta/meta.dart';
void f({@required int? x}) {}
void g() {
f();
}
常見修正方式
#提供必要的值
import 'package:meta/meta.dart';
void f({@required int? x}) {}
void g() {
f(x: 2);
}
遺失的傳回
#此函式的傳回類型為 '{0}',但未以 return 陳述式結尾。
描述
#任何未以明確 return 或 throw 結尾的函式或方法都會隱含傳回 null
。這很少是期望的行為。當分析器找到隱含傳回時,會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 f
未以 return 結尾
int f(int x) {
if (x < 0) {
return 0;
}
}
常見修正方式
#新增 return
陳述式,使傳回值明確,即使 null
是適當的值。
carray遺失大小註解
#類型為 'Array' 的欄位必須正好有一個 'Array' 註解。
描述
#當 Struct
或 Union
的子類別中的欄位類型為 Array
,但沒有單個 Array
註解指示陣列的維度時,分析器會產生此診斷訊息。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼會產生此診斷訊息,因為欄位 a0
沒有 Array
註解
import 'dart:ffi';
final class C extends Struct {
external Array<Uint8> a0;
}
常見修正方式
#確保欄位上正好有一個 Array
註解
import 'dart:ffi';
final class C extends Struct {
@Array(8)
external Array<Uint8> a0;
}
遺失的變數模式
#邏輯或模式的此分支中遺失變數模式 '{0}'。
描述
#當邏輯或模式的一個分支未宣告在同一模式的另一個分支上宣告的變數時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為邏輯或模式的右手邊未宣告變數 a
void f((int, int) r) {
if (r case (var a, 0) || (0, _)) {
print(a);
}
}
常見修正方式
#如果需要在受控陳述式中參考變數,則請將變數的宣告新增至邏輯或模式的每個分支
void f((int, int) r) {
if (r case (var a, 0) || (0, var a)) {
print(a);
}
}
如果不需要在受控陳述式中參考變數,則請從邏輯或模式的每個分支中移除變數的宣告
void f((int, int) r) {
if (r case (_, 0) || (0, _)) {
print('found a zero');
}
}
如果只有在模式的一個分支符合時才需要參考變數,而在另一個分支符合時則不需要,則請將模式分成兩部分
void f((int, int) r) {
switch (r) {
case (var a, 0):
print(a);
case (0, _):
print('found a zero');
}
}
mixin應用具體父類別叫用成員類型
#Super 呼叫的成員 '{0}' 的類型為 '{1}',而類別中的具體成員的類型為 '{2}'。
描述
#當在類別中使用 mixin,且該 mixin 使用 super
調用方法,但該方法的具體實作與 mixin 的 on
類型為該方法定義的簽章不同時,分析器會產生此診斷訊息。之所以會發生錯誤,是因為 mixin 中的調用可能會以與實際執行的方法不相容的方式調用該方法。
範例
#以下程式碼會產生此診斷訊息,因為類別 C
使用 mixin M
,mixin M
使用 super
調用 foo
,且在 I
(mixin 的 on
類型)中宣告的抽象版本的 foo
與在 A
中宣告的具體版本的 foo
簽章不同
class I {
void foo([int? p]) {}
}
class A {
void foo(int p) {}
}
abstract class B extends A implements I {
@override
void foo([int? p]);
}
mixin M on I {
void bar() {
super.foo(42);
}
}
abstract class C extends B with M {}
常見修正方式
#如果類別不需要使用 mixin,則請從 with
子句中移除它
class I {
void foo([int? p]) {}
}
class A {
void foo(int? p) {}
}
abstract class B extends A implements I {
@override
void foo([int? p]);
}
mixin M on I {
void bar() {
super.foo(42);
}
}
abstract class C extends B {}
如果類別需要使用 mixin,則請確保方法的具體實作符合 mixin 期望的簽章
class I {
void foo([int? p]) {}
}
class A {
void foo(int? p) {}
}
abstract class B extends A implements I {
@override
void foo([int? p]) {
super.foo(p);
}
}
mixin M on I {
void bar() {
super.foo(42);
}
}
abstract class C extends B with M {}
mixin應用未實作介面
#'{0}' 無法混入 '{1}',因為 '{1}' 未實作 '{2}'。
描述
#當具有超類別約束的 mixin 用於mixin 應用,但其超類別未實作必要的約束時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 mixin M
要求應用它的類別必須是 A
的子類別,但 Object
不是 A
的子類別
class A {}
mixin M on A {}
class X = Object with M;
常見修正方式
#如果您需要使用 mixin,則請將超類別變更為與超類別約束相同或為其子類別
class A {}
mixin M on A {}
class X = A with M;
mixin應用沒有具體的父類別叫用成員
#類別沒有 super 呼叫成員 '{0}' 的具體實作。
類別沒有 super 呼叫 setter '{0}' 的具體實作。
描述
#當mixin 應用包含從其超類別調用成員,且 mixin 應用的超類別中沒有該名稱的具體成員時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 mixin M
包含調用 super.m()
,且類別 A
(即 mixin 應用 A+M
的超類別)未定義 m
的具體實作
abstract class A {
void m();
}
mixin M on A {
void bar() {
super.m();
}
}
abstract class B extends A with M {}
常見修正方式
#如果您打算將 mixin M
應用於不同的類別,即具有 m
的具體實作的類別,則請將 B
的超類別變更為該類別
abstract class A {
void m();
}
mixin M on A {
void bar() {
super.m();
}
}
class C implements A {
void m() {}
}
abstract class B extends C with M {}
如果您需要使 B
成為 A
的子類別,則請在 A
中新增 m
的具體實作
abstract class A {
void m() {}
}
mixin M on A {
void bar() {
super.m();
}
}
abstract class B extends A with M {}
mixin類別宣告擴充非物件
#類別 '{0}' 無法宣告為 mixin,因為它擴展了 'Object' 以外的類別。
描述
#當標記為 mixin
修飾詞的類別擴展了 'Object' 以外的類別時,分析器會產生此診斷訊息。mixin 類別不能有 'Object' 以外的超類別。
範例
#以下程式碼會產生此診斷訊息,因為具有修飾詞 mixin
的類別 B
擴展了 A
class A {}
mixin class B extends A {}
常見修正方式
#如果您希望將類別用作 mixin,則請將超類別變更為 Object
,可以明確變更,也可以移除 extends 子句來變更
class A {}
mixin class B {}
如果類別需要具有 'Object' 以外的超類別,則請移除 mixin
修飾詞
class A {}
class B extends A {}
如果您既需要 mixin 又需要 'Object' 以外的類別的子類別,則請將子類別的成員移至新的 mixin,從子類別中移除 mixin
修飾詞,並將新的 mixin 應用於子類別
class A {}
class B extends A with M {}
mixin M {}
根據子類別的成員,這可能需要為 mixin 新增 on
子句。
mixin類別宣告建構子
#類別 '{0}' 無法用作 mixin,因為它宣告了建構子。
描述
#當類別用作 mixin,且混入的類別定義了建構子時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為類別 A
(定義了建構子)正在用作 mixin
//@dart=2.19
class A {
A();
}
class B with A {}
常見修正方式
#如果可以將類別轉換為 mixin,則請執行轉換
mixin A {
}
class B with A {}
如果類別不能是 mixin,且可以移除建構子,則請執行移除
//@dart=2.19
class A {
}
class B with A {}
如果類別不能是 mixin,且您無法移除建構子,則請嘗試擴展或實作類別,而不是混入它
class A {
A();
}
class B extends A {}
mixin繼承自非物件
#類別 '{0}' 無法用作 mixin,因為它擴展了 'Object' 以外的類別。
描述
#當擴展了 'Object' 以外的類別的類別用作 mixin 時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為類別 B
(擴展了 A
)正被 C
用作 mixin
//@dart=2.19
class A {}
class B extends A {}
class C with B {}
常見修正方式
#如果用作 mixin 的類別可以變更為擴展 Object
,則請變更它
//@dart=2.19
class A {}
class B {}
class C with B {}
如果用作 mixin 的類別無法變更,且使用它的類別擴展了 Object
,則請擴展用作 mixin 的類別
class A {}
class B extends A {}
class C extends B {}
如果類別未擴展 Object
,或者您希望能夠在其他位置混入 B
的行為,則請建立真正的 mixin
class A {}
mixin M on A {}
class B extends A with M {}
class C extends A with M {}
mixin具現化
#Mixin 無法實例化。
描述
#當 mixin 被實例化時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 mixin M
正在被實例化
mixin M {}
var m = M();
常見修正方式
#如果您打算使用類別的實例,則請使用該類別的名稱來取代 mixin 的名稱。
mixin的非類別
#類別只能混入 mixin 和類別。
描述
#當 with
子句中的名稱定義為 mixin 或類別以外的其他項目時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 F
定義為函式類型
typedef F = int Function(String);
class C with F {}
常見修正方式
#從清單中移除無效的名稱,可能會將其替換為預期的 mixin 或類別的名稱
typedef F = int Function(String);
class C {}
sealed_類別上的_mixin
#類別 '{0}' 不應作為 mixin 約束使用,因為它是 sealed 類別,且任何混入此 mixin 的類別都必須以 '{0}' 作為超類別。
描述
#當 mixin 的超類別約束是來自不同套件的類別,且該類別標記為 sealed
時,分析器會產生此診斷訊息。 Sealed 類別無法擴展、實作、混入或用作超類別約束。
範例
#如果套件 p
定義了 sealed 類別
import 'package:meta/meta.dart';
@sealed
class C {}
則以下程式碼在套件 p
以外的套件中時,會產生此診斷訊息
import 'package:p/p.dart';
mixin M on C {}
常見修正方式
#如果使用 mixin 的類別不需要成為 sealed 類別的子類別,則請考慮新增欄位並委派給 sealed 類別的包裝實例。
mixin_父類別限制延遲載入類別
#延遲類別無法用作超類別約束。
描述
#當 mixin 的超類別約束是從延遲載入的程式庫匯入時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 math.Random
的超類別約束是從延遲載入的程式庫匯入
import 'dart:async' deferred as async;
mixin M<T> on async.Stream<T> {}
常見修正方式
#如果匯入不需要延遲載入,則請移除 deferred
關鍵字
import 'dart:async' as async;
mixin M<T> on async.Stream<T> {}
如果匯入確實需要延遲載入,則請移除超類別約束
mixin M<T> {}
mixin_父類別限制非介面
#只有類別和 mixin 可以用作超類別約束。
描述
#當 mixin 宣告中 on
關鍵字後面的類型既不是類別也不是 mixin 時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 F
既不是類別也不是 mixin
typedef F = void Function();
mixin M on F {}
常見修正方式
#如果類型原本應為類別,但輸入錯誤,則請替換名稱。
否則,請從 on
子句中移除類型。
多個重新導向建構子調用
#建構子最多只能有一個 'this' 重新導向。
描述
#當建構子重新導向到同一個類別中的多個其他建構子 (使用 this
) 時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 C
中的未命名建構子同時重新導向到 this.a
和 this.b
class C {
C() : this.a(), this.b();
C.a();
C.b();
}
常見修正方式
#移除所有重新導向,僅保留一個
class C {
C() : this.a();
C.a();
C.b();
}
多個_super_初始化器
#建構子最多只能有一個 'super' 初始化運算式。
描述
#當建構子的初始化運算式清單包含多個從超類別調用建構子的情況時,分析器會產生此診斷訊息。初始化運算式清單必須正好有一個此類呼叫,可以是明確的或隱含的。
範例
#以下程式碼會產生此診斷訊息,因為 B
的建構子的初始化運算式清單同時調用了超類別 A
中的建構子 one
和建構子 two
class A {
int? x;
String? s;
A.one(this.x);
A.two(this.s);
}
class B extends A {
B() : super.one(0), super.two('');
}
常見修正方式
#如果其中一個 super 建構子將完全初始化實例,則請移除另一個
class A {
int? x;
String? s;
A.one(this.x);
A.two(this.s);
}
class B extends A {
B() : super.one(0);
}
如果其中一個 super 建構子實現的初始化可以在建構子的主體中執行,則請移除其 super 調用,並在主體中執行初始化
class A {
int? x;
String? s;
A.one(this.x);
A.two(this.s);
}
class B extends A {
B() : super.one(0) {
s = '';
}
}
如果初始化只能在超類別的建構子中執行,則請新增新的建構子,或修改現有的建構子之一,以便有一個建構子允許在單次呼叫中完成所有必要的初始化
class A {
int? x;
String? s;
A.one(this.x);
A.two(this.s);
A.three(this.x, this.s);
}
class B extends A {
B() : super.three(0, '');
}
必須是原生函式類型
#給予 '{1}' 的類型 '{0}' 必須是有效的 'dart:ffi' 原生函式類型。
描述
#當調用 Pointer.fromFunction
、DynamicLibrary.lookupFunction
或 NativeCallable
建構子時,其類型引數(無論是明確的還是推斷的)不是原生函式類型時,分析器會產生此診斷訊息。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼會產生此診斷訊息,因為類型 T
可以是 Function
的任何子類別,但 fromFunction
的類型引數必須是原生函式類型
import 'dart:ffi';
int f(int i) => i * 2;
class C<T extends Function> {
void g() {
Pointer.fromFunction<T>(f, 0);
}
}
常見修正方式
#使用原生函式類型作為調用的類型引數
import 'dart:ffi';
int f(int i) => i * 2;
class C<T extends Function> {
void g() {
Pointer.fromFunction<Int32 Function(Int32)>(f, 0);
}
}
必須是子類型
#對於 '{2}',類型 '{0}' 必須是 '{1}' 的子類型。
描述
#分析器在兩種情況下會產生此診斷訊息
- 在
Pointer.fromFunction
的調用中,或NativeCallable
建構子中,類型引數(無論是明確的還是推斷的)不是傳遞為方法第一個引數的函式類型的超類型。 - 在
DynamicLibrary.lookupFunction
的調用中,第一個類型引數不是第二個類型引數的超類型。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼會產生此診斷訊息,因為函式 f
的類型 (String Function(int)
) 不是類型引數 T
(Int8 Function(Int8)
) 的子類型
import 'dart:ffi';
typedef T = Int8 Function(Int8);
double f(double i) => i;
void g() {
Pointer.fromFunction<T>(f, 5.0);
}
常見修正方式
#如果函式正確,則請變更類型引數以符合
import 'dart:ffi';
typedef T = Float Function(Float);
double f(double i) => i;
void g() {
Pointer.fromFunction<T>(f, 5.0);
}
如果類型引數正確,則請變更函式以符合
import 'dart:ffi';
typedef T = Int8 Function(Int8);
int f(int i) => i;
void g() {
Pointer.fromFunction<T>(f, 5);
}
必須是不可變的
#此類別(或此類別繼承自的類別)標記為 '@immutable',但其一個或多個實例欄位不是 final:{0}
描述
#當不可變類別定義了一個或多個非 final 的實例欄位時,分析器會產生此診斷訊息。如果類別使用註解 immutable
標記為不可變,或者它是不可變類別的子類別,則該類別是不可變的。
範例
#以下程式碼會產生此診斷,因為欄位 x
不是 final
import 'package:meta/meta.dart';
@immutable
class C {
int x;
C(this.x);
}
常見修正方式
#如果類別的實例應該是不可變的,則請將關鍵字 final
新增至所有非 final 欄位宣告
import 'package:meta/meta.dart';
@immutable
class C {
final int x;
C(this.x);
}
如果類別的實例應該是可變的,則請移除註解,或者如果註解是繼承的,則選擇不同的超類別
class C {
int x;
C(this.x);
}
必須呼叫_super
#此方法覆寫了 '{0}' 中標註為 '@mustCallSuper' 的方法,但未調用覆寫的方法。
描述
#當覆寫標註為 mustCallSuper
的方法的方法未按要求調用覆寫的方法時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 B
中的方法 m
未調用 A
中覆寫的方法 m
import 'package:meta/meta.dart';
class A {
@mustCallSuper
m() {}
}
class B extends A {
@override
m() {}
}
常見修正方式
#在覆寫方法中新增覆寫方法的調用
import 'package:meta/meta.dart';
class A {
@mustCallSuper
m() {}
}
class B extends A {
@override
m() {
super.m();
}
}
必須傳回_void
#傳遞給 'NativeCallable.listener' 的函式的傳回類型必須是 'void',而不是 '{0}'。
描述
#當您將不傳回 void
的函式傳遞給 NativeCallable.listener
建構子時,分析器會產生此診斷訊息。
NativeCallable.listener
建立一個可以從任何執行緒調用的原生可調用物件。調用可調用物件的原生程式碼會將訊息傳回給建立可調用物件的隔離區,且不會等待回應。因此,無法從可調用物件傳回結果。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼會產生此診斷訊息,因為函式 f
傳回 int
而不是 void
。
import 'dart:ffi';
int f(int i) => i * 2;
void g() {
NativeCallable<Int32 Function(Int32)>.listener(f);
}
常見修正方式
#將函式的傳回類型變更為 void
。
import 'dart:ffi';
void f(int i) => print(i * 2);
void g() {
NativeCallable<Void Function(Int32)>.listener(f);
}
名稱不是字串
#'name' 欄位的值必須是字串。
描述
#當最上層 name
鍵的值不是字串時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 name
鍵後面的值是一個清單
name:
- example
常見修正方式
#將值替換為字串
name: example
原生欄位無效的類型
#'{0}' 是原生欄位不支援的類型。原生欄位僅支援指標、陣列或數值和複合類型。
描述
#當 @Native
註解的欄位具有原生欄位不支援的類型時,分析器會產生此診斷訊息。
原生欄位支援指標、陣列、數值類型和 Compound
的子類型(即 struct 或 union)。NativeType
的其他子類型,例如 Handle
或 NativeFunction
,不允許作為原生欄位。
原生函式應與外部函式一起使用,而不是外部欄位。
不支援 Handle,因為無法透明地將 Dart 物件載入和儲存到指標中。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼會產生此診斷訊息,因為欄位 free
使用了不支援的原生類型 NativeFunction
import 'dart:ffi';
@Native<NativeFunction<Void Function()>>()
external void Function() free;
常見修正方式
#如果您打算使用 NativeFunction
欄位繫結到現有的原生函式,請改用 @Native
方法
import 'dart:ffi';
@Native<Void Function(Pointer<Void>)>()
external void free(Pointer<Void> ptr);
若要繫結到 C 中儲存函式指標的欄位,請為 Dart 欄位使用指標類型
import 'dart:ffi';
@Native()
external Pointer<NativeFunction<Void Function(Pointer<Void>)>> free;
原生欄位遺失類型
#無法推斷此欄位的原生類型,必須在註解中指定。
描述
#當 @Native
註解的欄位需要在註解中提供類型提示才能推斷原生類型時,分析器會產生此診斷訊息。
Dart 類型(例如 int
和 double
)具有多種可能的原生表示法。由於需要在編譯時知道原生類型,以便在存取欄位時產生正確的載入和儲存指令,因此必須提供明確的類型。
範例
#以下程式碼會產生此診斷訊息,因為欄位 f
的類型為 int
(有多種原生表示法),但在 Native
註解上沒有明確的類型參數
import 'dart:ffi';
@Native()
external int f;
常見修正方式
#若要修正此診斷訊息,請從欄位的原生宣告中找出正確的原生表示法。然後,將對應的類型新增至註解。例如,如果 f
在 C 中宣告為 uint8_t
,則 Dart 欄位應宣告為
import 'dart:ffi';
@Native<Uint8>()
external int f;
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
原生欄位不是靜態的
#原生欄位必須是靜態的。
描述
#當類別中的實例欄位標註了 @Native
時,分析器會產生此診斷訊息。原生欄位是指 C、C++ 或其他原生語言中的全域變數,而 Dart 中的實例欄位特定於該類別的實例。因此,原生欄位必須是靜態的。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼會產生此診斷訊息,因為類別 C
中的欄位 f
是 @Native
,但不是 static
import 'dart:ffi';
class C {
@Native<Int>()
external int f;
}
常見修正方式
#將欄位設為靜態
import 'dart:ffi';
class C {
@Native<Int>()
external static int f;
}
或將其移出類別,在這種情況下,不需要明確的 static
修飾詞
import 'dart:ffi';
class C {
}
@Native<Int>()
external int f;
如果您打算註解應為 struct 一部分的實例欄位,請省略 @Native
註解
import 'dart:ffi';
final class C extends Struct {
@Int()
external int f;
}
原生函式遺失類型
#無法推斷此函式的原生類型,因此必須在註解中指定。
描述
#當 @Native
註解的函式需要在註解中提供類型提示才能推斷原生函式類型時,分析器會產生此診斷訊息。
Dart 類型(例如 int
和 double
)具有多種可能的原生表示法。由於需要在編譯時知道原生類型,以便為函式產生正確的繫結和呼叫指令,因此必須提供明確的類型。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼會產生此診斷訊息,因為函式 f()
的傳回類型為 int
,但在 Native
註解上沒有明確的類型參數
import 'dart:ffi';
@Native()
external int f();
常見修正方式
#將對應的類型新增至註解。例如,如果 f()
在 C 中宣告為傳回 int32_t
,則 Dart 函式應宣告為
import 'dart:ffi';
@Native<Int32 Function()>()
external int f();
負數變數維度
#可變長度陣列的變數維度必須是非負數。
描述
#分析器在兩種情況下會產生此診斷。
第一種情況是 Array.variableWithVariableDimension
註解中給定的變數維度為負數。變數維度是註解中的第一個引數。
第二種情況是 Array.variableMulti
註解中給定的變數維度為負數。變數維度在註解的 variableDimension
引數中指定。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼會產生此診斷訊息,因為在 Array.variableWithVariableDimension
註解中提供了變數維度 -1
import 'dart:ffi';
final class MyStruct extends Struct {
@Array.variableWithVariableDimension(-1)
external Array<Uint8> a0;
}
以下程式碼會產生此診斷訊息,因為在 Array.variableMulti
註解中提供了變數維度 -1
import 'dart:ffi';
final class MyStruct2 extends Struct {
@Array.variableMulti(variableDimension: -1, [1, 2])
external Array<Array<Array<Uint8>>> a0;
}
常見修正方式
#將變數維度變更為零 (0
) 或正數
import 'dart:ffi';
final class MyStruct extends Struct {
@Array.variableWithVariableDimension(1)
external Array<Uint8> a0;
}
將變數維度變更為零 (0
) 或正數
import 'dart:ffi';
final class MyStruct2 extends Struct {
@Array.variableMulti(variableDimension: 1, [1, 2])
external Array<Array<Array<Uint8>>> a0;
}
具有未定義建構子預設值的_new
#類別 '{0}' 沒有未命名的建構子。
描述
#當在定義了具名建構子的類別上調用未命名的建構子,但該類別沒有未命名的建構子時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 A
未定義未命名的建構子
class A {
A.a();
}
A f() => A();
常見修正方式
#如果其中一個具名建構子可以滿足您的需求,則請使用它
class A {
A.a();
}
A f() => A.a();
如果沒有具名建構子可以滿足您的需求,且您可以新增未命名的建構子,則請新增建構子
class A {
A();
A.a();
}
A f() => A();
非抽象類別繼承抽象成員
#遺失 '{0}' 的具體實作。
遺失 '{0}' 和 '{1}' 的具體實作。
遺失 '{0}'、'{1}'、'{2}'、'{3}' 和其他 {4} 個的具體實作。
遺失 '{0}'、'{1}'、'{2}' 和 '{3}' 的具體實作。
遺失 '{0}'、'{1}' 和 '{2}' 的具體實作。
描述
#當具體類別繼承了一個或多個抽象成員,且未為至少其中一個抽象成員提供或繼承實作時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為類別 B
沒有 m
的具體實作
abstract class A {
void m();
}
class B extends A {}
常見修正方式
#如果子類別可以為某些或所有繼承的抽象成員提供具體實作,則請新增具體實作
abstract class A {
void m();
}
class B extends A {
void m() {}
}
如果存在提供繼承方法實作的 mixin,則請將 mixin 應用於子類別
abstract class A {
void m();
}
class B extends A with M {}
mixin M {
void m() {}
}
如果子類別無法為所有繼承的抽象成員提供具體實作,則請將子類別標記為抽象類別
abstract class A {
void m();
}
abstract class B extends A {}
非布林條件
#條件必須具有 'bool' 的靜態類型。
描述
#當條件(例如 if
或 while
迴圈)沒有 bool
的靜態類型時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 x
具有 int
的靜態類型
void f(int x) {
if (x) {
// ...
}
}
常見修正方式
#變更條件,使其產生布林值
void f(int x) {
if (x == 0) {
// ...
}
}
非布林運算式
#assert 中的運算式必須為 'bool' 類型。
描述
#當 assert 中的第一個運算式的類型不是 bool
時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 p
的類型為 int
,但需要 bool
void f(int p) {
assert(p);
}
常見修正方式
#變更運算式,使其具有 bool
類型
void f(int p) {
assert(p > 0);
}
非布林否定運算式
#否定運算元必須具有 'bool' 的靜態類型。
描述
#當一元否定運算子 (!
) 的運算元沒有 bool
類型時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 x
是 int
,但它必須是 bool
int x = 0;
bool y = !x;
常見修正方式
#將運算元替換為具有 bool
類型的運算式
int x = 0;
bool y = !(x > 0);
非布林運算元
#運算子 '{0}' 的運算元必須可指派給 'bool'。
描述
#當 &&
或 ||
運算子之一的運算元沒有 bool
類型時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 a
不是布林值
int a = 3;
bool b = a || a > 1;
常見修正方式
#將運算元變更為布林值
int a = 3;
bool b = a == 0 || a > 1;
非常數註解建構子
#註解建立只能呼叫 const 建構子。
描述
#當註解是對現有建構子的調用,即使調用的建構子不是 const 建構子時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 C
的建構子不是 const 建構子
@C()
void f() {
}
class C {
C();
}
常見修正方式
#如果類別可以具有 const 建構子,則請建立可用於註解的 const 建構子
@C()
void f() {
}
class C {
const C();
}
如果類別不能具有 const 建構子,則請移除註解,或為註解使用不同的類別。
非常數_case_運算式
#Case 運算式必須是常數。
描述
#當 case
子句中的運算式不是常數運算式時,分析器會產生此診斷訊息。
範例
#下列程式碼會產生此診斷,因為 j
不是常數
void f(int i, int j) {
switch (i) {
case j:
// ...
break;
}
}
常見修正方式
#請將運算式設為常數運算式,或將 switch
述句改寫為一連串的 if
述句
void f(int i, int j) {
if (i == j) {
// ...
}
}
來自延遲載入程式庫的非常數_case_運算式
#延遲載入函式庫的常數值不能做為 case 運算式使用。
描述
#當 case 子句中的運算式參照到使用延遲匯入的函式庫中的常數時,分析器會產生此診斷。為了讓 switch 述句能夠有效率地編譯,case 子句中參照的常數必須在編譯時期可用,而延遲載入函式庫中的常數在編譯時期是不可用的。
有關更多資訊,請查看 延遲載入程式庫。
範例
#給定一個檔案 a.dart
,它定義了常數 zero
const zero = 0;
下列程式碼會產生此診斷,因為函式庫 a.dart
是使用 deferred
匯入,且在 case 子句中使用了匯入函式庫中宣告的常數 a.zero
import 'a.dart' deferred as a;
void f(int x) {
switch (x) {
case a.zero:
// ...
break;
}
}
常見修正方式
#如果您需要參照匯入函式庫中的常數,請移除 deferred
關鍵字
import 'a.dart' as a;
void f(int x) {
switch (x) {
case a.zero:
// ...
break;
}
}
如果您需要參照匯入函式庫中的常數,且也需要延遲匯入該函式庫,請將 switch 述句改寫為一連串的 if
述句
import 'a.dart' deferred as a;
void f(int x) {
if (x == a.zero) {
// ...
}
}
如果您不需要參照常數,請替換 case 運算式
void f(int x) {
switch (x) {
case 0:
// ...
break;
}
}
非常數預設值
#選用參數的預設值必須是常數。
描述
#當具名或位置選用參數的預設值不是編譯時期常數時,分析器會產生此診斷。
範例
#下列程式碼會產生此診斷訊息
var defaultValue = 3;
void f([int value = defaultValue]) {}
常見修正方式
#如果預設值可以轉換為常數,請轉換它
const defaultValue = 3;
void f([int value = defaultValue]) {}
如果預設值需要隨時間變更,請在函式內部套用預設值
var defaultValue = 3;
void f([int? value]) {
value ??= defaultValue;
}
來自延遲載入程式庫的非常數預設值
#延遲載入函式庫的常數值不能做為預設參數值使用。
描述
#當選用參數的預設值使用從延遲匯入的函式庫匯入的常數時,分析器會產生此診斷。預設值需要在編譯時期可用,而延遲載入函式庫中的常數在編譯時期是不可用的。
有關更多資訊,請查看 延遲載入程式庫。
範例
#給定一個檔案 a.dart
,它定義了常數 zero
const zero = 0;
下列程式碼會產生此診斷,因為 zero
是在使用延遲匯入的函式庫中宣告的
import 'a.dart' deferred as a;
void f({int x = a.zero}) {}
常見修正方式
#如果您需要參照匯入函式庫中的常數,請移除 deferred
關鍵字
import 'a.dart' as a;
void f({int x = a.zero}) {}
如果您不需要參照常數,請替換預設值
void f({int x = 0}) {}
非常數清單元素
#常數列表常值中的值必須是常數。
描述
#當常數列表常值中的元素不是常數值時,分析器會產生此診斷。列表常值可以是明確的常數 (因為它以 const
關鍵字作為前綴) 或隱含的常數 (因為它出現在常數情境中)。
範例
#下列程式碼會產生此診斷,因為 x
不是常數,即使它出現在隱含的常數列表常值中
var x = 2;
var y = const <int>[0, 1, x];
常見修正方式
#如果列表需要是常數列表,請將元素轉換為常數。在上述範例中,您可以將 const
關鍵字新增至 x
的宣告中
const x = 2;
var y = const <int>[0, 1, x];
如果運算式無法設為常數,則列表也不能是常數,因此您必須變更程式碼,使列表不是常數。在上述範例中,這表示移除列表常值之前的 const
關鍵字
var x = 2;
var y = <int>[0, 1, x];
非常數_map_元素
#常數映射常值中的元素必須是常數。
描述
#當常數映射中的 if
元素或展開元素不是常數元素時,分析器會產生此診斷。
範例
#下列程式碼會產生此診斷,因為它嘗試展開非常數映射
var notConst = <int, int>{};
var map = const <int, int>{...notConst};
同樣地,下列程式碼會產生此診斷,因為 if
元素中的條件不是常數運算式
bool notConst = true;
var map = const <int, int>{if (notConst) 1 : 2};
常見修正方式
#如果映射需要是常數映射,請將元素設為常數。在展開範例中,您可以將要展開的集合設為常數來做到這一點
const notConst = <int, int>{};
var map = const <int, int>{...notConst};
如果映射不需要是常數映射,請移除 const
關鍵字
bool notConst = true;
var map = <int, int>{if (notConst) 1 : 2};
非常數_map_金鑰
#常數映射常值中的鍵必須是常數。
描述
#當常數映射常值中的鍵不是常數值時,分析器會產生此診斷。
範例
#下列程式碼會產生此診斷,因為 a
不是常數
var a = 'a';
var m = const {a: 0};
常見修正方式
#如果映射需要是常數映射,請將鍵設為常數
const a = 'a';
var m = const {a: 0};
如果映射不需要是常數映射,請移除 const
關鍵字
var a = 'a';
var m = {a: 0};
非常數_map_模式金鑰
#映射模式中的鍵運算式必須是常數。
描述
#當映射模式中的鍵不是常數運算式時,分析器會產生此診斷。
範例
#下列程式碼會產生此診斷,因為鍵 A()
不是常數
void f(Object x) {
if (x case {A(): 0}) {}
}
class A {
const A();
}
常見修正方式
#請使用常數作為鍵
void f(Object x) {
if (x case {const A(): 0}) {}
}
class A {
const A();
}
非常數_map_值
#常數映射常值中的值必須是常數。
描述
#當常數映射常值中的值不是常數值時,分析器會產生此診斷。
範例
#下列程式碼會產生此診斷,因為 a
不是常數
var a = 'a';
var m = const {0: a};
常見修正方式
#如果映射需要是常數映射,請將鍵設為常數
const a = 'a';
var m = const {0: a};
如果映射不需要是常數映射,請移除 const
關鍵字
var a = 'a';
var m = {0: a};
非常數關係模式運算式
#關係模式運算式必須是常數。
描述
#當關係模式運算式中的值不是常數運算式時,分析器會產生此診斷。
範例
#下列程式碼會產生此診斷,因為 >
運算子的運算元 a
不是常數
final a = 0;
void f(int x) {
if (x case > a) {}
}
常見修正方式
#請將值替換為常數運算式
const a = 0;
void f(int x) {
if (x case > a) {}
}
非常數_set_元素
#常數集合常值中的值必須是常數。
描述
#當常數集合常值包含不是編譯時期常數的元素時,分析器會產生此診斷。
範例
#以下程式碼會產生此診斷,因為 i
不是常數
var i = 0;
var s = const {i};
常見修正方式
#如果元素可以變更為常數,請變更它
const i = 0;
var s = const {i};
如果元素不能是常數,請移除關鍵字 const
var i = 0;
var s = {i};
非常數類型引數
#「{0}」的型別引數必須在編譯時期已知,因此它們不能是型別參數。
描述
#當方法的型別引數需要於編譯時期已知,但使用了型別參數 (其值在編譯時期可能未知) 作為型別引數時,分析器會產生此診斷。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#下列程式碼會產生此診斷,因為 Pointer.asFunction
的型別引數必須在編譯時期已知,但是型別參數 R
(在編譯時期未知) 正被用作型別引數
import 'dart:ffi';
typedef T = int Function(int);
class C<R extends T> {
void m(Pointer<NativeFunction<T>> p) {
p.asFunction<R>();
}
}
常見修正方式
#請移除任何型別參數的使用
import 'dart:ffi';
class C {
void m(Pointer<NativeFunction<Int64 Function(Int64)>> p) {
p.asFunction<int Function(int)>();
}
}
const_參數的非常數引數
#引數 '{0}' 必須是常數。
描述
#當參數使用 mustBeConst
註解標註,且對應的引數不是常數運算式時,分析器會產生此診斷。
範例
#下列程式碼會在函式 f
的調用上產生此診斷,因為傳遞給函式 g
的引數值不是常數
import 'package:meta/meta.dart' show mustBeConst;
int f(int value) => g(value);
int g(@mustBeConst int value) => value + 1;
常見修正方式
#如果有可用的合適常數可以使用,請將引數替換為常數
import 'package:meta/meta.dart' show mustBeConst;
const v = 3;
int f() => g(v);
int g(@mustBeConst int value) => value + 1;
字面值建構子的非常數呼叫
#這個執行個體建立必須是 'const',因為 {0} 建構子標記為 '@literal'。
描述
#當具有 literal
註解的建構子在沒有使用 const
關鍵字的情況下被調用,但建構子的所有引數都是常數時,分析器會產生此診斷。此註解表示建構子應盡可能用於建立常數值。
範例
#下列程式碼會產生此診斷訊息
import 'package:meta/meta.dart';
class C {
@literal
const C();
}
C f() => C();
常見修正方式
#請在建構子調用之前新增關鍵字 const
import 'package:meta/meta.dart';
class C {
@literal
const C();
}
void f() => const C();
非常數產生器列舉建構子
#生成式列舉建構子必須是 'const'。
描述
#當列舉宣告包含未標記為 const
的生成式建構子時,分析器會產生此診斷。
範例
#下列程式碼會產生此診斷,因為 E
中的建構子未標記為 const
enum E {
e;
E();
}
常見修正方式
#請在建構子之前新增 const
關鍵字
enum E {
e;
const E();
}
表示法類型中非變異數類型參數位置
#擴充型別參數不能在其表示型別的非協變位置中使用。
描述
#當擴充型別的型別參數在該擴充型別的表示型別中的非協變位置中使用時,分析器會產生此診斷。
範例
#下列程式碼會產生此診斷,因為型別參數 T
在函式型別 void Function(T)
中用作參數型別,而參數不是協變的
extension type A<T>(void Function(T) f) {}
常見修正方式
#請移除型別參數的使用
extension type A(void Function(String) f) {}
非詳盡的_switch_運算式
#類型「{0}」未被 switch case 完全比對,因為它與「{1}」不符。
描述
#當 switch
運算式缺少一個或多個可能流經它的值的情況時,分析器會產生此診斷。
範例
#下列程式碼會產生此診斷,因為 switch 運算式沒有值 E.three
的 case
enum E { one, two, three }
String f(E e) => switch (e) {
E.one => 'one',
E.two => 'two',
};
常見修正方式
#如果遺失的值對於 switch 運算式具有明顯的意義,請為每個遺失比對的值新增一個 case
enum E { one, two, three }
String f(E e) => switch (e) {
E.one => 'one',
E.two => 'two',
E.three => 'three',
};
如果遺失的值不需要比對,請新增一個萬用字元模式,以傳回簡單的預設值
enum E { one, two, three }
String f(E e) => switch (e) {
E.one => 'one',
E.two => 'two',
_ => 'unknown',
};
請注意,萬用字元模式將處理未來新增至類型中的任何值。如果 switch
需要更新以考量新新增的類型,您將失去讓編譯器警告您的能力。
非詳盡的_switch_陳述式
#類型「{0}」未被 switch case 完全比對,因為它與「{1}」不符。
描述
#當針對窮舉類型進行 switch 切換的 switch
述句缺少一個或多個可能流經它的值的情況時,分析器會產生此診斷。
範例
#下列程式碼會產生此診斷,因為 switch 述句沒有值 E.three
的 case,且 E
是窮舉類型
enum E { one, two, three }
void f(E e) {
switch (e) {
case E.one:
case E.two:
}
}
常見修正方式
#請為每個目前未比對的常數新增一個 case
enum E { one, two, three }
void f(E e) {
switch (e) {
case E.one:
case E.two:
break;
case E.three:
}
}
如果遺失的值不需要比對,請新增 default
子句或萬用字元模式
enum E { one, two, three }
void f(E e) {
switch (e) {
case E.one:
case E.two:
break;
default:
}
}
但請注意,新增 default
子句或萬用字元模式將導致也處理窮舉類型的任何未來值,因此如果 switch
需要更新,您將失去讓編譯器警告您的能力。
列舉中非_final_欄位
#列舉只能宣告 final 欄位。
描述
#當列舉中的執行個體欄位未標記為 final
時,分析器會產生此診斷。
範例
#下列程式碼會產生此診斷,因為欄位 f
不是 final 欄位
enum E {
c;
int f = 0;
}
常見修正方式
#如果欄位必須為列舉定義,請將欄位標記為 final
enum E {
c;
final int f = 0;
}
如果可以移除欄位,請移除它
enum E {
c
}
非產生器建構子
#預期的生成式建構子 '{0}',但找到工廠建構子。
描述
#當建構子的初始化列表調用父類別的建構子,且調用的建構子是工廠建構子時,分析器會產生此診斷。只有生成式建構子可以在初始化列表中調用。
範例
#下列程式碼會產生此診斷,因為建構子 super.one()
的調用正在調用工廠建構子
class A {
factory A.one() = B;
A.two();
}
class B extends A {
B() : super.one();
}
常見修正方式
#請變更 super 調用以調用生成式建構子
class A {
factory A.one() = B;
A.two();
}
class B extends A {
B() : super.two();
}
如果生成式建構子是未命名的建構子,且如果沒有引數傳遞給它,則您可以移除 super 調用。
非產生器隱含建構子
#父類別 '{0}' 的未命名建構子 (由 '{1}' 的預設建構子調用) 必須是生成式建構子,但找到工廠建構子。
描述
#當類別具有隱含的生成式建構子,且父類別具有明確的未命名工廠建構子時,分析器會產生此診斷。子類別中的隱含建構子隱含地調用父類別中的未命名建構子,但生成式建構子只能調用另一個生成式建構子,而不能調用工廠建構子。
範例
#下列程式碼會產生此診斷,因為 B
中的隱含建構子調用 A
中的未命名建構子,但 A
中的建構子是工廠建構子,而需要的是生成式建構子
class A {
factory A() => throw 0;
A.named();
}
class B extends A {}
常見修正方式
#如果父類別中的未命名建構子可以是生成式建構子,請將其變更為生成式建構子
class A {
A();
A.named();
}
class B extends A { }
如果未命名建構子不能是生成式建構子,且父類別中還有其他生成式建構子,請明確調用其中一個
class A {
factory A() => throw 0;
A.named();
}
class B extends A {
B() : super.named();
}
如果沒有可用的生成式建構子,且無法新增任何建構子,請實作父類別而不是擴充它
class A {
factory A() => throw 0;
A.named();
}
class B implements A {}
指標的非原生函式類型引數
#無法調用 'asFunction',因為指標的函式簽章 '{0}' 不是有效的 C 函式簽章。
描述
#當在原生函式的指標上調用方法 asFunction
,但原生函式的簽章不是有效的 C 函式簽章時,分析器會產生此診斷。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#下列程式碼會產生此診斷,因為與指標 p
相關聯的函式簽章 (FNative
) 不是有效的 C 函式簽章
import 'dart:ffi';
typedef FNative = int Function(int);
typedef F = int Function(int);
class C {
void f(Pointer<NativeFunction<FNative>> p) {
p.asFunction<F>();
}
}
常見修正方式
#請將 NativeFunction
簽章設為有效的 C 簽章
import 'dart:ffi';
typedef FNative = Int8 Function(Int8);
typedef F = int Function(int);
class C {
void f(Pointer<NativeFunction<FNative>> p) {
p.asFunction<F>();
}
}
非正數陣列維度
#陣列維度必須是正數。
描述
#當在 Array
註解中給定的維度小於或等於零 (0
) 時,分析器會產生此診斷。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#下列程式碼會產生此診斷,因為提供了 -8
的陣列維度
import 'dart:ffi';
final class MyStruct extends Struct {
@Array(-8)
external Array<Uint8> a0;
}
常見修正方式
#請將維度變更為正整數
import 'dart:ffi';
final class MyStruct extends Struct {
@Array(8)
external Array<Uint8> a0;
}
如果這是可變長度內聯陣列,請將註解變更為 Array.variable()
import 'dart:ffi';
final class MyStruct extends Struct {
@Array.variable()
external Array<Uint8> a0;
}
非尺寸類型引數
#類型 '{1}' 不是 '{0}' 的有效型別引數。型別引數必須是原生整數、「Float」、「Double」、「Pointer」或「Struct」、「Union」或「AbiSpecificInteger」的子類型。
描述
#當類別 Array
的型別引數不是有效類型之一時,分析器會產生此診斷:原生整數、Float
、Double
、Pointer
或 Struct
、Union
或 AbiSpecificInteger
的子類型。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#下列程式碼會產生此診斷,因為 Array
的型別引數是 Void
,而 Void
不是有效類型之一
import 'dart:ffi';
final class C extends Struct {
@Array(8)
external Array<Void> a0;
}
常見修正方式
#請將型別引數變更為有效類型之一
import 'dart:ffi';
final class C extends Struct {
@Array(8)
external Array<Uint8> a0;
}
非同步_factory
#工廠主體不能使用 'async'、'async*' 或 'sync*'。
描述
#當工廠建構子的主體標記為 async
、async*
或 sync*
時,分析器會產生此診斷。所有建構子 (包括工廠建構子) 都必須傳回在其中宣告它們的類別的執行個體,而不是 Future
、Stream
或 Iterator
。
範例
#下列程式碼會產生此診斷,因為工廠建構子的主體標記為 async
class C {
factory C() async {
return C._();
}
C._();
}
常見修正方式
#如果成員必須宣告為工廠建構子,請移除出現在主體之前的關鍵字
class C {
factory C() {
return C._();
}
C._();
}
如果成員必須傳回非封閉類別的執行個體,請將成員設為靜態方法
class C {
static Future<C> m() async {
return C._();
}
C._();
}
非類型作為類型引數
#名稱 '{0}' 不是類型,因此不能用作型別引數。
描述
#當不是類型的識別碼被用作型別引數時,分析器會產生此診斷。
範例
#以下程式碼產生此診斷訊息,因為 x
是一個變數,而不是型別。
var x = 0;
List<x> xList = [];
常見修正方式
#請將型別引數變更為類型
var x = 0;
List<int> xList = [];
catch_子句中的非類型
#名稱 '{0}' 不是類型,且不能在 on-catch 子句中使用。
描述
#當 catch
子句中 on
後面的識別碼定義為類型以外的其他內容時,分析器會產生此診斷。
範例
#下列程式碼會產生此診斷,因為 f
是函式,而不是類型
void f() {
try {
// ...
} on f {
// ...
}
}
常見修正方式
#請將名稱變更為應捕捉的物件的類型
void f() {
try {
// ...
} on FormatException {
// ...
}
}
運算子的非_void傳回
#運算子 []= 的傳回類型必須是 'void'。
描述
#當運算子 []=
的宣告具有 void
以外的傳回類型時,分析器會產生此診斷。
範例
#下列程式碼會產生此診斷,因為運算子 []=
的宣告具有 int
的傳回類型
class C {
int operator []=(int index, int value) => 0;
}
常見修正方式
#請將傳回類型變更為 void
class C {
void operator []=(int index, int value) => 0;
}
setter的非_void傳回
#setter 的傳回類型必須是 'void' 或不存在。
描述
#當 setter 定義為 void
以外的傳回類型時,分析器會產生此診斷。
範例
#下列程式碼會產生此診斷,因為 setter p
的傳回類型為 int
class C {
int set p(int i) => 0;
}
常見修正方式
#請將傳回類型變更為 void
或省略傳回類型
class C {
set p(int i) => 0;
}
未賦值的潛在非可為 Null 區域變數
#不可為 Null 的區域變數 '{0}' 必須在使用前指派值。
描述
#當區域變數被參照且具有以下所有特性時,分析器會產生此診斷
- 具有潛在不可為 Null的類型。
- 沒有初始化子。
- 未標記為
late
。 - 根據明確賦值的規範,分析器無法證明區域變數會在參照之前被指派值。
範例
#下列程式碼會產生此診斷,因為 x
不能具有 null
值,但在指派值之前被參照
String f() {
int x;
return x.toString();
}
下列程式碼會產生此診斷,因為對 x
的指派可能未執行,因此它可能具有 null
值
int g(bool b) {
int x;
if (b) {
x = 1;
}
return x * 2;
}
下列程式碼會產生此診斷,因為根據明確賦值分析,分析器無法證明 x
不會在未指派值的情況下被參照
int h(bool b) {
int x;
if (b) {
x = 1;
}
if (b) {
return x * 2;
}
return 0;
}
常見修正方式
#如果 null
是有效值,請使變數可為 Null
String f() {
int? x;
return x!.toString();
}
如果 null
不是有效值,且有合理的預設值,請新增初始化子
int g(bool b) {
int x = 2;
if (b) {
x = 1;
}
return x * 2;
}
否則,請確保在存取值之前,在每個可能的程式碼路徑上都已指派值
int g(bool b) {
int x;
if (b) {
x = 1;
} else {
x = 2;
}
return x * 2;
}
您也可以將變數標記為 late
,這會移除診斷,但如果變數在存取之前未指派值,則會在執行時期導致擲回例外狀況。只有當您確定變數始終會被指派值時,才應使用此方法,即使分析器無法根據明確賦值分析證明這一點。
int h(bool b) {
late int x;
if (b) {
x = 1;
}
if (b) {
return x * 2;
}
return 0;
}
不是類型
#{0} 不是類型。
描述
#當名稱用作類型,但宣告為類型以外的其他內容時,分析器會產生此診斷。
範例
#下列程式碼會產生此診斷,因為 f
是函式
f() {}
g(f v) {}
常見修正方式
#請將名稱替換為類型的名稱。
不是二元運算子
#'{0}' 不是二元運算子。
描述
#當只能用作一元運算子的運算子被用作二元運算子時,分析器會產生此診斷。
範例
#下列程式碼會產生此診斷,因為運算子 ~
只能用作一元運算子
var a = 5 ~ 3;
常見修正方式
#請將運算子替換為正確的二元運算子
var a = 5 - 3;
位置引數不足
#'{0}' 預期 1 個位置引數,但找到 0 個。
預期 1 個位置引數,但找到 0 個。
'{2}' 預期 {0} 個位置引數,但找到 {1} 個。
預期 {0} 個位置引數,但找到 {1} 個。
描述
#當方法或函式調用具有的位置引數少於所需位置參數的數量時,分析器會產生此診斷。
範例
#下列程式碼會產生此診斷,因為 f
宣告了兩個必要參數,但僅提供了一個引數
void f(int a, int b) {}
void g() {
f(0);
}
常見修正方式
#請新增與剩餘參數對應的引數
void f(int a, int b) {}
void g() {
f(0, 1);
}
未初始化的非可為 Null 實例欄位
#不可為 Null 的執行個體欄位 '{0}' 必須初始化。
描述
#當宣告欄位且具有以下所有特性時,分析器會產生此診斷
- 具有潛在不可為 Null的類型
- 沒有初始化子
- 未標記為
late
範例
#下列程式碼會產生此診斷,因為 x
在不允許為 null
時隱含地初始化為 null
class C {
int x;
}
同樣地,下列程式碼會產生此診斷,因為 x
在不允許為 null
時,被其中一個建構子隱含地初始化為 null
,即使它被其他建構子初始化也是如此
class C {
int x;
C(this.x);
C.n();
}
常見修正方式
#如果欄位存在適用於所有執行個體的合理預設值,請新增初始化運算式
class C {
int x = 0;
}
如果欄位的值應在建立執行個體時提供,請新增一個設定欄位值的建構子,或更新現有的建構子
class C {
int x;
C(this.x);
}
您也可以將欄位標記為 late
,這會移除診斷,但如果欄位在存取之前未指派值,則會在執行時期導致擲回例外狀況。只有當您確定欄位始終會在被參照之前指派值時,才應使用此方法。
class C {
late int x;
}
未初始化的非可為 Null 變數
#不可為 Null 的變數 '{0}' 必須初始化。
描述
#當靜態欄位或頂層變數具有不可為 Null 的類型且沒有初始化子時,分析器會產生此診斷。沒有初始化子的欄位和變數通常會初始化為 null
,但欄位或變數的類型不允許將其設定為 null
,因此必須提供明確的初始化子。
範例
#下列程式碼會產生此診斷,因為欄位 f
無法初始化為 null
class C {
static int f;
}
同樣地,下列程式碼會產生此診斷,因為頂層變數 v
無法初始化為 null
int v;
常見修正方式
#如果欄位或變數無法初始化為 null
,請新增一個將其設定為不可為 Null 值的初始化子
class C {
static int f = 0;
}
如果欄位或變數應初始化為 null
,請將類型變更為可為 Null
int? v;
如果欄位或變數無法在宣告中初始化,但始終會在被參照之前初始化,請將其標記為 late
class C {
static late int f;
}
非可迭代的展開
#列表或集合常值中的展開元素必須實作 'Iterable'。
描述
#當出現在列表常值或集合常值中的展開元素的靜態類型未實作類型 Iterable
時,分析器會產生此診斷。
範例
#下列程式碼會產生此診斷訊息
var m = <String, int>{'a': 0, 'b': 1};
var s = <String>{...m};
常見修正方式
#最常見的修正方法是用產生可迭代物件的運算式替換運算式
var m = <String, int>{'a': 0, 'b': 1};
var s = <String>{...m.keys};
非_map_展開
#映射常值中的展開元素必須實作 'Map'。
描述
#當出現在映射常值中的展開元素的靜態類型未實作類型 Map
時,分析器會產生此診斷。
範例
#下列程式碼會產生此診斷,因為 l
不是 Map
var l = <String>['a', 'b'];
var m = <int, String>{...l};
常見修正方式
#最常見的修正方法是用產生映射的運算式替換運算式
var l = <String>['a', 'b'];
var m = <int, String>{...l.asMap()};
沒有註解建構子引數
#註解建立必須具有引數。
描述
#當註解由單一識別碼組成,但該識別碼是類別名稱而不是變數名稱時,分析器會產生此診斷。若要建立類別的執行個體,識別碼後面必須跟著引數列表。
範例
#下列程式碼會產生此診斷,因為 C
是類別,而類別不能用作註解,除非從類別調用 const
建構子
class C {
const C();
}
@C
var x;
常見修正方式
#請新增遺失的引數列表
class C {
const C();
}
@C()
var x;
沒有組合的_super_簽章
#無法從覆寫的方法:{1},在 '{0}' 中推論遺失的類型。
描述
#當存在方法宣告,其中一個或多個類型需要推論,且這些類型無法推論,因為根據覆寫推論的規範,沒有任何覆寫方法的函式類型是所有其他覆寫方法的超類型時,分析器會產生此診斷。
範例
#下列程式碼會產生此診斷,因為在類別 C
中宣告的方法 m
遺失了傳回類型和參數 a
的類型,且這兩個遺失的類型都無法為其推論
abstract class A {
A m(String a);
}
abstract class B {
B m(int a);
}
abstract class C implements A, B {
m(a);
}
在此範例中,無法執行覆寫推論,因為覆寫的方法在以下方面不相容
- 參數類型 (
String
和int
) 皆不是對方的超類型。 - 傳回類型皆不是對方的子類型。
常見修正方式
#如果可能,請將與所有覆寫方法中的類型一致的類型新增至子類別中的方法
abstract class A {
A m(String a);
}
abstract class B {
B m(int a);
}
abstract class C implements A, B {
C m(Object a);
}
父類別中沒有產生器建構子
#類別 '{0}' 無法擴充 '{1}',因為 '{1}' 只有工廠建構子 (沒有生成式建構子),且 '{0}' 至少有一個生成式建構子。
描述
#當至少有一個生成式建構子 (無論是明確或隱含) 的類別具有沒有任何生成式建構子的父類別時,分析器會產生此診斷。每個生成式建構子 (Object
中定義的建構子除外) 都會明確或隱含地調用其父類別中的生成式建構子之一。
範例
#下列程式碼會產生此診斷,因為類別 B
具有隱含的生成式建構子,該建構子無法調用 A
中的生成式建構子,因為 A
沒有任何生成式建構子
class A {
factory A.none() => throw '';
}
class B extends A {}
常見修正方式
#如果父類別應具有生成式建構子,請新增一個
class A {
A();
factory A.none() => throw '';
}
class B extends A {}
如果子類別不應具有生成式建構子,請透過新增工廠建構子來移除它
class A {
factory A.none() => throw '';
}
class B extends A {
factory B.none() => throw '';
}
如果子類別必須具有生成式建構子,但父類別不能有,請實作父類別而不是擴充它
class A {
factory A.none() => throw '';
}
class B implements A {}
catch_子句中的可為 Null 類型
#潛在可為 Null 的類型不能在 'on' 子句中使用,因為擲回可為 Null 的運算式是無效的。
描述
#當 catch
子句中 on
後面的類型是可為 Null 的類型時,分析器會產生此診斷。指定可為 Null 的類型是無效的,因為捕捉 null
是不可能的 (因為擲回 null
是執行時期錯誤)。
範例
#下列程式碼會產生此診斷,因為指定的例外狀況類型允許 null
,但 null
無法被擲回
void f() {
try {
// ...
} on FormatException? {
}
}
常見修正方式
#請從類型中移除問號
void f() {
try {
// ...
} on FormatException {
}
}
extends_子句中的可為 Null 類型
#類別無法擴充可為 Null 的類型。
描述
#當類別宣告使用 extends
子句來指定父類別,且父類別後面跟著 ?
時,分析器會產生此診斷。
指定可為 Null 的父類別是無效的,因為這樣做沒有意義;它不會變更包含 extends
子句的類別所繼承的介面或實作。
但請注意,將可為 Null 的類型用作父類別的型別引數是有效的,例如 class A extends B<C?> {}
。
範例
#下列程式碼會產生此診斷,因為 A?
是可為 Null 的類型,且可為 Null 的類型不能在 extends
子句中使用
class A {}
class B extends A? {}
常見修正方式
#請從類型中移除問號
class A {}
class B extends A {}
implements_子句中的可為 Null 類型
#類別、mixin 或擴充型別無法實作可為 Null 的類型。
描述
#當類別、mixin 或擴充型別宣告具有 implements
子句,且介面後面跟著 ?
時,分析器會產生此診斷。
指定可為 Null 的介面是無效的,因為這樣做沒有意義;它不會變更包含 implements
子句的類別所繼承的介面。
但請注意,將可為 Null 的類型用作介面的型別引數是有效的,例如 class A implements B<C?> {}
。
範例
#下列程式碼會產生此診斷,因為 A?
是可為 Null 的類型,且可為 Null 的類型不能在 implements
子句中使用
class A {}
class B implements A? {}
常見修正方式
#請從類型中移除問號
class A {}
class B implements A {}
on_子句中的可為 Null 類型
#mixin 不能將可為 Null 的類型作為父類別約束。
描述
#當 mixin 宣告使用 on
子句來指定父類別約束,且指定的類別後面跟著 ?
時,分析器會產生此診斷。
指定可為 Null 的父類別約束是無效的,因為這樣做沒有意義;它不會變更包含 on
子句的 mixin 所依賴的介面。
但請注意,將可為 Null 的類型用作父類別約束的型別引數是有效的,例如 mixin A on B<C?> {}
。
範例
#下列程式碼會產生此診斷,因為 A?
是可為 Null 的類型,且可為 Null 的類型不能在 on
子句中使用
class C {}
mixin M on C? {}
常見修正方式
#請從類型中移除問號
class C {}
mixin M on C {}
with_子句中的可為 Null 類型
#類別或 mixin 無法混入可為 Null 的類型。
描述
#當類別或 mixin 宣告具有 with
子句,且 mixin 後面跟著 ?
時,分析器會產生此診斷。
指定可為 Null 的 mixin 是無效的,因為這樣做沒有意義;它不會變更包含 with
子句的類別所繼承的介面或實作。
但請注意,將可為 Null 的類型用作 mixin 的型別引數是有效的,例如 class A with B<C?> {}
。
範例
#下列程式碼會產生此診斷,因為 A?
是可為 Null 的類型,且可為 Null 的類型不能在 with
子句中使用
mixin M {}
class C with M? {}
常見修正方式
#請從類型中移除問號
mixin M {}
class C with M {}
null引數給非_null類型
#不應使用 'null' 引數調用 '{0}' 作為不可為 Null 的型別引數 '{1}'。
描述
#當 null
傳遞給建構子 Future.value
或方法 Completer.complete
時,如果用於建立執行個體的型別引數是不可為 Null 的,則分析器會產生此診斷。即使類型系統無法表達此限制,傳入 null
也會導致執行時期例外狀況。
範例
#下列程式碼會產生此診斷,因為 null
正傳遞給建構子 Future.value
,即使型別引數是不可為 Null 的類型 String
也是如此
Future<String> f() {
return Future.value(null);
}
常見修正方式
#請傳入不可為 Null 的值
Future<String> f() {
return Future.value('');
}
null檢查永遠失敗
#此 null 檢查將始終擲回例外狀況,因為運算式將始終評估為 'null'。
描述
#當 null 檢查運算子 (!
) 用於值只能是 null
的運算式時,分析器會產生此診斷。在這種情況下,運算子始終會擲回例外狀況,這可能不是預期的行為。
範例
#下列程式碼會產生此診斷,因為函式 g
將始終傳回 null
,這表示 f
中的 null 檢查將始終擲回例外狀況
void f() {
g()!;
}
Null g() => null;
常見修正方式
#如果您打算始終擲回例外狀況,請將 null 檢查替換為明確的 throw
運算式,以使意圖更明確
void f() {
g();
throw TypeError();
}
Null g() => null;
已過時的冒號作為預設值
#不再支援在預設值之前使用冒號作為分隔符號。
描述
#當冒號 (:
) 用作選用具名參數的預設值之前的分隔符號時,分析器會產生此診斷。雖然過去允許此語法,但已將其移除,改為使用等號 (=
)。
範例
#以下程式碼會產生此診斷,因為在選用參數 i
的預設值之前使用了冒號
void f({int i : 0}) {}
常見修正方式
#請將冒號替換為等號
void f({int i = 0}) {}
on重複
#類型 '{0}' 只能在父類別約束中包含一次。
描述
#當相同的類型在 mixin 的父類別約束中多次列出時,分析器會產生此診斷。
範例
#下列程式碼會產生此診斷,因為 A
在 M
的父類別約束中包含兩次
mixin M on A, A {
}
class A {}
class B {}
常見修正方式
#如果應在父類別約束中包含不同的類型,請將其中一個出現次數替換為另一個類型
mixin M on A, B {
}
class A {}
class B {}
如果沒有預期其他類型,請移除重複的類型名稱
mixin M on A {
}
class A {}
class B {}
運算子中的選用參數
#定義運算子時不允許選用參數。
描述
#當運算子宣告中的一個或多個參數是選用參數時,分析器會產生此診斷。
範例
#下列程式碼會產生此診斷,因為參數 other
是選用參數
class C {
C operator +([C? other]) => this;
}
常見修正方式
#請使所有參數成為必要參數
class C {
C operator +(C other) => this;
}
非覆寫成員的覆寫
#欄位未覆寫繼承的 getter 或 setter。
getter 未覆寫繼承的 getter。
方法未覆寫繼承的方法。
setter 未覆寫繼承的 setter。
描述
#當類別成員使用 @override
註解標註,但該成員未在類別的任何父類型中宣告時,分析器會產生此診斷。
範例
#下列程式碼會產生此診斷,因為 m
未在 C
的任何父類型中宣告
class C {
@override
String m() => '';
}
常見修正方式
#如果成員旨在覆寫名稱不同的成員,請更新成員以具有相同的名稱
class C {
@override
String toString() => '';
}
如果成員旨在覆寫已從父類別中移除的成員,請考慮從子類別中移除成員。
如果無法移除成員,請移除註解。
packed註解
#Structs 必須最多有一個 'Packed' 註解。
描述
#當 Struct
的子類別具有多個 Packed
註解時,分析器會產生此診斷。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#下列程式碼會產生此診斷,因為類別 C
(Struct
的子類別) 具有兩個 Packed
註解
import 'dart:ffi';
@Packed(1)
@Packed(1)
final class C extends Struct {
external Pointer<Uint8> notEmpty;
}
常見修正方式
#移除除了其中一個註解之外的所有註解
import 'dart:ffi';
@Packed(1)
final class C extends Struct {
external Pointer<Uint8> notEmpty;
}
packed註解對齊
#僅支援封裝為 1、2、4、8 和 16 個位元組。
描述
#當 Packed
註解的引數不是允許的值之一時:1、2、4、8 或 16,分析器會產生此診斷。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#下列程式碼會產生此診斷,因為 Packed
註解的引數 (3
) 不是允許的值之一
import 'dart:ffi';
@Packed(3)
final class C extends Struct {
external Pointer<Uint8> notEmpty;
}
常見修正方式
#請將對齊方式變更為允許的值之一
import 'dart:ffi';
@Packed(4)
final class C extends Struct {
external Pointer<Uint8> notEmpty;
}
不同程式庫的_part_of
#預期此函式庫是 '{0}' 的一部分,而不是 '{1}'。
描述
#當函式庫嘗試將檔案作為自身的一部分包含時,如果另一個檔案是不同函式庫的一部分,則分析器會產生此診斷。
範例
#給定一個包含以下內容的檔案 part.dart
part of 'library.dart';
下列程式碼 (在 library.dart
以外的任何檔案中) 會產生此診斷,因為它嘗試將 part.dart
作為自身的一部分包含,而 part.dart
是不同函式庫的一部分
part 'package:a/part.dart';
常見修正方式
#如果函式庫應使用不同的檔案作為一部分,請將 part 指示詞中的 URI 變更為另一個檔案的 URI。
如果part 檔案應為此函式庫的一部分,請更新 part-of 指示詞中的 URI (或函式庫名稱) 以成為正確函式庫的 URI (或名稱)。
非_part的_part_of
#包含的 part '{0}' 必須具有 part-of 指示詞。
描述
#當找到 part 指示詞,且參照的檔案沒有 part-of 指示詞時,分析器會產生此診斷。
範例
#假設檔案 a.dart
包含
class A {}
下列程式碼會產生此診斷,因為 a.dart
不包含 part-of 指示詞
part 'a.dart';
常見修正方式
#如果參照的檔案旨在成為另一個函式庫的一部分,請將 part-of 指示詞新增至檔案
part of 'test.dart';
class A {}
如果參考的檔案旨在作為一個程式庫,則將 part 指令替換為 import 指令
import 'a.dart';
未命名程式庫的_part_of
#程式庫未命名。在 part-of 指令中,預期的是 URI,而不是程式庫名稱 '{0}'。
描述
#當一個沒有 library
指令(因此沒有名稱)的程式庫包含 part
指令,且部分檔案中的 part of
指令使用名稱來指定它所屬的程式庫時,分析器會產生此診斷訊息。
範例
#假設一個名為 part_file.dart
的部分檔案包含以下程式碼
part of lib;
以下程式碼產生此診斷訊息,因為包含部分檔案的程式庫沒有名稱,即使部分檔案使用名稱來指定它所屬的程式庫
part 'part_file.dart';
常見修正方式
#變更部分檔案中的 part of
指令,以 URI 指定其程式庫
part of 'test.dart';
路徑不存在
#路徑 '{0}' 不存在。
描述
#當相依性具有 path
鍵,且該鍵參考到一個不存在的目錄時,分析器會產生此診斷訊息。
範例
#假設目錄 doesNotExist
不存在,以下程式碼會產生此診斷訊息,因為它被列為套件的路徑
name: example
dependencies:
local_package:
path: doesNotExist
常見修正方式
#如果路徑正確,則在該路徑建立一個目錄。
如果路徑不正確,則變更路徑以符合套件根目錄的路徑。
路徑不是_POSIX
#路徑 '{0}' 不是 POSIX 樣式的路徑。
描述
#當相依性具有 path
鍵,且其值為字串,但不是 POSIX 樣式的路徑時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 path
鍵後面的路徑是 Windows 路徑
name: example
dependencies:
local_package:
path: E:\local_package
常見修正方式
#將路徑轉換為 POSIX 路徑。
路徑_pubspec不存在
#目錄 '{0}' 不包含 pubspec。
描述
#當相依性具有 path
鍵,且該鍵參考到一個不包含 pubspec.yaml
檔案的目錄時,分析器會產生此診斷訊息。
範例
#假設目錄 local_package
不包含檔案 pubspec.yaml
,以下程式碼會產生此診斷訊息,因為它被列為套件的路徑
name: example
dependencies:
local_package:
path: local_package
常見修正方式
#如果路徑旨在作為套件的根目錄,則在目錄中新增 pubspec.yaml
檔案
name: local_package
如果路徑錯誤,則將其替換為正確的路徑。
模式賦值不是區域變數
#模式賦值中只能賦值給區域變數。
描述
#當模式賦值將值賦值給區域變數以外的任何項目時,分析器會產生此診斷訊息。模式無法賦值給欄位或頂層變數。
範例
#如果使用模式解構程式碼更簡潔,則重寫程式碼以在模式宣告中將值賦值給區域變數,並單獨賦值給非區域變數
class C {
var x = 0;
void f((int, int) r) {
(x, _) = r;
}
}
常見修正方式
#如果使用模式賦值程式碼更簡潔,則重寫程式碼以將值賦值給區域變數,並單獨賦值給非區域變數
class C {
var x = 0;
void f((int, int) r) {
var (a, _) = r;
x = a;
}
}
如果未使用模式賦值程式碼更簡潔,則重寫程式碼以不使用模式賦值
class C {
var x = 0;
void f((int, int) r) {
x = r.$1;
}
}
來自延遲載入程式庫的模式常數
#延遲程式庫中的常數值無法在模式中使用。
描述
#當模式包含在不同程式庫中宣告的值,且該程式庫是使用延遲匯入來匯入時,分析器會產生此診斷訊息。常數在編譯時評估,但延遲程式庫中的值在編譯時不可用。
有關更多資訊,請查看 延遲載入程式庫。
範例
#給定一個檔案 a.dart
,它定義了常數 zero
const zero = 0;
以下程式碼會產生此診斷訊息,因為常數模式 a.zero
是使用延遲匯入來匯入的
import 'a.dart' deferred as a;
void f(int x) {
switch (x) {
case a.zero:
// ...
break;
}
}
常見修正方式
#如果您需要參照匯入函式庫中的常數,請移除 deferred
關鍵字
import 'a.dart' as a;
void f(int x) {
switch (x) {
case a.zero:
// ...
break;
}
}
如果您需要參照匯入函式庫中的常數,且也需要延遲匯入該函式庫,請將 switch 述句改寫為一連串的 if
述句
import 'a.dart' deferred as a;
void f(int x) {
if (x == a.zero) {
// ...
}
}
如果您不需要參照常數,請替換 case 運算式
void f(int x) {
switch (x) {
case 0:
// ...
break;
}
}
不可反駁情境中的模式類型不符
#類型為 '{0}' 的比對值無法賦值給所需的類型 '{1}'。
描述
#當模式賦值或模式宣告右側的值的類型,與用於比對它的模式所需類型不符時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 x
可能不是 String
,因此可能不符合物件模式
void f(Object x) {
var String(length: a) = x;
print(a);
}
常見修正方式
#變更程式碼,使右側運算式的類型符合模式所需的類型
void f(String x) {
var String(length: a) = x;
print(a);
}
防護中的模式變數賦值
#模式變數無法在封閉的受保護模式的 guard 內部賦值。
描述
#當模式變數在 guard (when
) 子句內部被賦值時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為變數 a
在 guard 子句內部被賦值
void f(int x) {
if (x case var a when (a = 1) > 0) {
print(a);
}
}
常見修正方式
#如果有一個您需要捕獲的值,則將其賦值給不同的變數
void f(int x) {
var b;
if (x case var a when (b = 1) > 0) {
print(a + b);
}
}
如果沒有您需要捕獲的值,則移除賦值
void f(int x) {
if (x case var a when 1 > 0) {
print(a);
}
}
不允許的平台值
#platforms
欄位中的鍵不能有值。
描述
#當 platforms
映射中的鍵具有值時,分析器會產生此診斷訊息。若要深入瞭解如何指定您的套件支援的平台,請查看關於平台宣告的文件。
範例
#以下 pubspec.yaml
會產生此診斷訊息,因為鍵 web
具有值。
name: example
platforms:
web: "chrome"
常見修正方式
#省略值並讓鍵沒有值
name: example
platforms:
web:
platforms
欄位中鍵的值目前保留供未來可能的行為使用。
物件模式中的位置欄位
#物件模式只能使用具名字段。
描述
#當物件模式包含一個欄位,但未指定 getter 名稱時,分析器會產生此診斷訊息。物件模式欄位會比對物件的 getter 回傳的值。在未指定 getter 名稱的情況下,模式欄位無法存取值以嘗試比對。
範例
#以下程式碼會產生此診斷訊息,因為物件模式 String(1)
未指定要存取 String
的哪個 getter 並與值 1
比較
void f(Object o) {
if (o case String(1)) {}
}
常見修正方式
#新增 getter 名稱以存取值,然後在要比對的模式之前加上冒號
void f(Object o) {
if (o case String(length: 1)) {}
}
具有位置引數的位置_super_形式參數
#當 super 建構子調用具有位置引數時,不能使用位置 super 參數。
描述
#當提供給超類別建構子的某些(但非全部)位置參數使用 super 參數時,分析器會產生此診斷訊息。
位置 super 參數透過索引與 super 建構子中的位置參數相關聯。也就是說,第一個 super 參數與 super 建構子中的第一個位置參數相關聯,第二個與第二個相關聯,依此類推。位置引數也是如此。同時具有位置 super 參數和位置引數表示有兩個值與超類別建構子中的同一個參數相關聯,因此不允許這樣做。
範例
#以下程式碼會產生此診斷訊息,因為建構子 B.new
正在使用 super 參數將其中一個必要的位置參數傳遞給 A
中的 super 建構子,但正在 super 建構子調用中明確傳遞另一個參數
class A {
A(int x, int y);
}
class B extends A {
B(int x, super.y) : super(x);
}
常見修正方式
#如果所有位置參數都可以是 super 參數,則將正常的位置參數轉換為 super 參數
class A {
A(int x, int y);
}
class B extends A {
B(super.x, super.y);
}
如果某些位置參數不能是 super 參數,則將 super 參數轉換為正常參數
class A {
A(int x, int y);
}
class B extends A {
B(int x, int y) : super(x, y);
}
前置詞與最上層成員衝突
#名稱 '{0}' 已用作匯入前綴,不能用於命名頂層元素。
描述
#當一個名稱同時用作匯入前綴和同一個程式庫中頂層宣告的名稱時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 f
同時用作匯入前綴和函式的名稱
import 'dart:math' as f;
int f() => f.min(0, 1);
常見修正方式
#如果您想將該名稱用於匯入前綴,則重新命名頂層宣告
import 'dart:math' as f;
int g() => f.min(0, 1);
如果您想將該名稱用於頂層宣告,則重新命名匯入前綴
import 'dart:math' as math;
int f() => math.min(0, 1);
前置詞識別項後面沒有點
#名稱 '{0}' 指的是匯入前綴,因此後面必須加上 '.'。
描述
#當匯入前綴單獨使用,而沒有存取與前綴相關聯的程式庫中宣告的任何名稱時,分析器會產生此診斷訊息。前綴不是變數,因此不能用作值。
範例
#以下程式碼會產生此診斷訊息,因為前綴 math
被當作變數使用
import 'dart:math' as math;
void f() {
print(math);
}
常見修正方式
#如果程式碼不完整,則參考與前綴相關聯的其中一個程式庫中的內容
import 'dart:math' as math;
void f() {
print(math.pi);
}
如果名稱錯誤,則更正名稱。
本機宣告遮蔽的前置詞
#前綴 '{0}' 無法在此處使用,因為它被區域宣告遮蔽。
描述
#當匯入前綴在一個上下文中使用,但由於被區域宣告遮蔽而不可見時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為前綴 a
用於存取類別 Future
,但由於它被參數 a
遮蔽而不可見
import 'dart:async' as a;
a.Future? f(int a) {
a.Future? x;
return x;
}
常見修正方式
#重新命名前綴
import 'dart:async' as p;
p.Future? f(int a) {
p.Future? x;
return x;
}
或重新命名區域變數
import 'dart:async' as a;
a.Future? f(int p) {
a.Future? x;
return x;
}
mixin應用中的私有衝突
#由 '{1}' 定義的私有名稱 '{0}' 與由 '{2}' 定義的同名衝突。
描述
#當兩個 mixin 定義相同的私有成員,且在定義 mixin 之外的程式庫中的單一類別中一起使用時,分析器會產生此診斷訊息。
範例
#假設一個名為 a.dart
的檔案包含以下程式碼
mixin A {
void _foo() {}
}
mixin B {
void _foo() {}
}
以下程式碼會產生此診斷訊息,因為 mixin A
和 B
都定義了方法 _foo
import 'a.dart';
class C extends Object with A, B {}
常見修正方式
#如果您不需要兩個 mixin,則從 with
子句中移除其中一個
import 'a.dart';
class C extends Object with A, B {}
如果您需要兩個 mixin,則重新命名兩個 mixin 之一中衝突的成員。
私有選用參數
#具名參數不能以下底線開頭。
描述
#當具名參數的名稱以下底線開頭時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為具名參數 _x
以下底線開頭
class C {
void m({int _x = 0}) {}
}
常見修正方式
#重新命名參數,使其不以下底線開頭
class C {
void m({int x = 0}) {}
}
私有_setter
#setter '{0}' 是私有的,無法在宣告它的程式庫外部存取。
描述
#當私有 setter 在一個它不可見的程式庫中使用時,分析器會產生此診斷訊息。
範例
#給定一個包含以下內容的檔案 a.dart
class A {
static int _f = 0;
}
以下程式碼會產生此診斷訊息,因為它參考了私有 setter _f
,即使該 setter 不可見
import 'a.dart';
void f() {
A._f = 0;
}
常見修正方式
#如果您可以將 setter 設為公開,則這樣做
class A {
static int f = 0;
}
如果您無法將 setter 設為公開,則尋找不同的方式來實作程式碼。
讀取可能未賦值的_final
#final 變數 '{0}' 無法讀取,因為它在此時可能尚未賦值。
描述
#當在宣告位置未初始化的 final 區域變數,在編譯器無法證明該變數在被參考之前總是已初始化的點被讀取時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 final 區域變數 x
在讀取時(第 3 行)可能尚未初始化
int f() {
final int x;
return x;
}
常見修正方式
#確保變數在讀取之前已初始化
int f(bool b) {
final int x;
if (b) {
x = 0;
} else {
x = 1;
}
return x;
}
記錄字面值一個位置沒有尾隨逗號
#只有一個位置欄位的記錄字面值需要尾隨逗號。
描述
#當只有單一位置欄位的記錄字面值在欄位後方沒有尾隨逗號時,分析器會產生此診斷訊息。
在某些位置,只有單一位置欄位的記錄字面值也可能是括號括住的運算式。需要尾隨逗號來消除這兩種有效解釋的歧義。
範例
#以下程式碼會產生此診斷訊息,因為記錄字面值有一個位置欄位,但沒有尾隨逗號
var r = const (1);
常見修正方式
#新增尾隨逗號
var r = const (1,);
記錄類型一個位置沒有尾隨逗號
#只有一個位置欄位的記錄類型需要尾隨逗號。
描述
#當只有單一位置欄位的記錄類型註解在欄位後方沒有尾隨逗號時,分析器會產生此診斷訊息。
在某些位置,只有單一位置欄位的記錄類型也可能是括號括住的運算式。需要尾隨逗號來消除這兩種有效解釋的歧義。
範例
#以下程式碼會產生此診斷訊息,因為記錄類型有一個位置欄位,但沒有尾隨逗號
void f((int) r) {}
常見修正方式
#新增尾隨逗號
void f((int,) r) {}
遞迴編譯時期常數
#編譯時期常數運算式依賴自身。
描述
#當編譯時期常數的值根據自身定義時(直接或間接),會產生無限迴圈,分析器會產生此診斷訊息。
範例
#以下程式碼會產生兩次此診斷訊息,因為兩個常數都是根據另一個常數定義的
const secondsPerHour = minutesPerHour * 60;
const minutesPerHour = secondsPerHour / 60;
常見修正方式
#透過尋找至少一種常數的替代定義方式來打破循環
const secondsPerHour = minutesPerHour * 60;
const minutesPerHour = 60;
遞迴建構子重新導向
#建構子無法直接或間接地重新導向自身。
描述
#當建構子直接或間接地重新導向自身時,會產生無限迴圈,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為產生器建構子 C.a
和 C.b
各自重新導向另一個
class C {
C.a() : this.b();
C.b() : this.a();
}
以下程式碼會產生此診斷訊息,因為工廠建構子 A
和 B
各自重新導向另一個
abstract class A {
factory A() = B;
}
class B implements A {
factory B() = A;
B.named();
}
常見修正方式
#在產生器建構子的情況下,透過定義至少一個不重新導向至另一個建構子的建構子來打破循環
class C {
C.a() : this.b();
C.b();
}
在工廠建構子的情況下,透過定義至少一個工廠建構子來打破循環,使其執行以下操作之一
- 重新導向至產生器建構子
abstract class A {
factory A() = B;
}
class B implements A {
factory B() = B.named;
B.named();
}
- 不重新導向至另一個建構子
abstract class A {
factory A() = B;
}
class B implements A {
factory B() {
return B.named();
}
B.named();
}
- 不是工廠建構子
abstract class A {
factory A() = B;
}
class B implements A {
B();
B.named();
}
遞迴介面繼承
#'{0}' 不能是自身的超介面:{1}。
'{0}' 不能擴充自身。
'{0}' 不能實作自身。
'{0}' 不能將自身用作 mixin。
'{0}' 不能將自身用作超類別約束。
描述
#當類型階層中存在循環性時,分析器會產生此診斷訊息。當一個類型直接或間接地宣告為自身的子類型時,就會發生這種情況。
範例
#以下程式碼會產生此診斷訊息,因為類別 A
宣告為 B
的子類型,而 B
是 A
的子類型
class A extends B {}
class B implements A {}
常見修正方式
#變更類型階層,使其沒有循環性。
非重新宣告成員的重新宣告
#{0} 未重新宣告超介面中宣告的 {0}。
描述
#當擴充功能類型的成員使用 @redeclare
註解,但已實作的介面中沒有任何成員具有相同名稱時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為擴充功能類型 E
宣告的成員 n
使用了 @redeclare
註解,但 C
沒有名為 n
的成員
import 'package:meta/meta.dart';
class C {
void m() {}
}
extension type E(C c) implements C {
@redeclare
void n() {}
}
常見修正方式
#如果註解的成員名稱正確,則移除註解
class C {
void m() {}
}
extension type E(C c) implements C {
void n() {}
}
如果註解的成員應該取代已實作介面中的成員,則變更註解成員的名稱以符合要取代的成員
import 'package:meta/meta.dart';
class C {
void m() {}
}
extension type E(C c) implements C {
@redeclare
void m() {}
}
重新導向產生器至遺失的建構子
#在 '{1}' 中找不到建構子 '{0}'。
描述
#當產生器建構子重新導向至未定義的建構子時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為建構子 C.a
重新導向至建構子 C.b
,但未定義 C.b
class C {
C.a() : this.b();
}
常見修正方式
#如果必須呼叫遺失的建構子,則定義它
class C {
C.a() : this.b();
C.b();
}
如果不需要呼叫遺失的建構子,則移除重新導向
class C {
C.a();
}
重新導向產生器至非產生器建構子
#產生器建構子無法重新導向至工廠建構子。
描述
#當產生器建構子重新導向至工廠建構子時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為產生器建構子 C.a
重新導向至工廠建構子 C.b
class C {
C.a() : this.b();
factory C.b() => C.a();
}
常見修正方式
#如果產生器建構子不需要重新導向至另一個建構子,則移除重新導向。
class C {
C.a();
factory C.b() => C.a();
}
如果產生器建構子必須重新導向至另一個建構子,則使另一個建構子成為產生器(非工廠)建構子
class C {
C.a() : this.b();
C.b();
}
重新導向至抽象類別建構子
#重新導向的建構子 '{0}' 無法重新導向至抽象類別 '{1}' 的建構子。
描述
#當建構子重新導向至抽象類別中的建構子時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 A
中的工廠建構子重新導向至 B
中的建構子,但 B
是抽象類別
class A {
factory A() = B;
}
abstract class B implements A {}
常見修正方式
#如果程式碼重新導向至正確的建構子,則變更類別使其不是抽象類別
class A {
factory A() = B;
}
class B implements A {}
否則,變更工廠建構子,使其重新導向至具體類別中的建構子,或具有具體實作。
重新導向至無效函式類型
#重新導向的建構子 '{0}' 與 '{1}' 的參數不相容。
描述
#當工廠建構子嘗試重新導向至另一個建構子,但兩者具有不相容的參數時,分析器會產生此診斷訊息。如果重新導向的建構子的所有參數都可以傳遞給另一個建構子,且另一個建構子不需要任何未由重新導向的建構子宣告的參數,則參數是相容的。
範例
#以下程式碼會產生此診斷訊息,因為 A
的建構子未宣告 B
的建構子需要的參數
abstract class A {
factory A() = B;
}
class B implements A {
B(int x);
B.zero();
}
以下程式碼會產生此診斷訊息,因為 A
的建構子宣告了一個具名參數 (y
),但 B
的建構子不允許
abstract class A {
factory A(int x, {int y}) = B;
}
class B implements A {
B(int x);
}
常見修正方式
#如果有與重新導向的建構子相容的不同建構子,則重新導向至該建構子
abstract class A {
factory A() = B.zero;
}
class B implements A {
B(int x);
B.zero();
}
否則,更新重新導向的建構子以使其相容
abstract class A {
factory A(int x) = B;
}
class B implements A {
B(int x);
}
重新導向至無效傳回類型
#重新導向的建構子的回傳類型 '{0}' 不是 '{1}' 的子類型。
描述
#當工廠建構子重新導向至一個建構子,但該建構子的回傳類型不是工廠建構子宣告產生的類型的子類型時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 A
不是 C
的子類別,這表示建構子 A()
回傳的值無法從建構子 C()
回傳
class A {}
class B implements C {}
class C {
factory C() = A;
}
常見修正方式
#如果工廠建構子重新導向至錯誤類別中的建構子,則更新工廠建構子以重新導向至正確的建構子
class A {}
class B implements C {}
class C {
factory C() = B;
}
如果定義要重新導向的建構子的類別是應該回傳的類別,則使其成為工廠回傳類型的子類型
class A implements C {}
class B implements C {}
class C {
factory C() = A;
}
重新導向至遺失的建構子
#在 '{1}' 中找不到建構子 '{0}'。
描述
#當建構子重新導向至不存在的建構子時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 A
中的工廠建構子重新導向至 B
中不存在的建構子
class A {
factory A() = B.name;
}
class B implements A {
B();
}
常見修正方式
#如果要重新導向的建構子是正確的,則定義該建構子
class A {
factory A() = B.name;
}
class B implements A {
B();
B.name();
}
如果應該調用不同的建構子,則更新重新導向
class A {
factory A() = B;
}
class B implements A {
B();
}
重新導向至非類別
#名稱 '{0}' 不是類型,不能在重新導向的建構子中使用。
描述
#實作工廠建構子的一種方法是透過參考建構子的名稱來重新導向至另一個建構子。當重新導向至建構子以外的其他項目時,分析器會產生此診斷訊息。
範例
#下列程式碼會產生此診斷,因為 f
是函式
C f() => throw 0;
class C {
factory C() = f;
}
常見修正方式
#如果未定義建構子,則定義它或將其替換為已定義的建構子。
如果已定義建構子,但定義它的類別不可見,則您可能需要新增匯入。
如果您嘗試回傳函式回傳的值,則重寫建構子以從建構子的主體回傳值
C f() => throw 0;
class C {
factory C() => f();
}
重新導向至非_const_建構子
#常數重新導向建構子無法重新導向至非常數建構子。
描述
#當標記為 const
的建構子重新導向至未標記為 const
的建構子時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為建構子 C.a
標記為 const
,但重新導向至未標記為 const
的建構子 C.b
class C {
const C.a() : this.b();
C.b();
}
常見修正方式
#如果非常數建構子可以標記為 const
,則將其標記為 const
class C {
const C.a() : this.b();
const C.b();
}
如果非常數建構子無法標記為 const
,則移除重新導向或從重新導向的建構子中移除 const
class C {
C.a() : this.b();
C.b();
}
重新導向至類型別名展開為類型參數
#重新導向的建構子無法重新導向至擴充為類型參數的類型別名。
描述
#當重新導向的工廠建構子重新導向至類型別名,且類型別名擴充為類型別名的類型參數之一時,分析器會產生此診斷訊息。這是不允許的,因為類型參數的值是類型而不是類別。
範例
#以下程式碼會產生此診斷訊息,因為重新導向至 B<A>
是指向一個類型別名,其值為 T
,即使它看起來值應該是 A
class A implements C {}
typedef B<T> = T;
abstract class C {
factory C() = B<A>;
}
常見修正方式
#使用類別名稱或定義為類別的類型別名,而不是定義為類型參數的類型別名
class A implements C {}
abstract class C {
factory C() = A;
}
在宣告之前參考
#區域變數 '{0}' 在宣告之前無法被參考。
描述
#當變數在宣告之前被參考時,分析器會產生此診斷訊息。在 Dart 中,變數在宣告它們的區塊中隨處可見,但只能在宣告後才能被參考。
分析器還會產生一個上下文訊息,指示宣告的位置。
範例
#以下程式碼會產生此診斷訊息,因為 i
在宣告之前被使用
void f() {
print(i);
int i = 5;
}
常見修正方式
#如果您打算參考區域變數,則將宣告移至第一次參考之前
void f() {
int i = 5;
print(i);
}
如果您打算參考來自外部範圍的名稱,例如參數、實例欄位或頂層變數,則重新命名區域宣告,使其不會隱藏外部變數。
void f(int i) {
print(i);
int x = 5;
print(x);
}
不可反駁情境中的可反駁模式
#可否決模式無法在不可否決的上下文中使用。
描述
#當可否決模式在僅允許不可否決模式的上下文中使用時,分析器會產生此診斷訊息。
不允許的可否決模式是
- 邏輯或
- 關係
- 空值檢查
- 常數
檢查的上下文是
- 基於模式的變數宣告
- 基於模式的 for 迴圈
- 左側帶有模式的賦值
範例
#以下程式碼會產生此診斷訊息,因為空值檢查模式(一種可否決模式)在基於模式的變數宣告中,而基於模式的變數宣告不允許可否決模式
void f(int? x) {
var (_?) = x;
}
常見修正方式
#重寫程式碼,使其不在不可否決的上下文中使用可否決模式。
關係模式運算元類型不可賦值
#常數運算式類型 '{0}' 不可賦值給 '{2}' 運算子的參數類型 '{1}'。
描述
#當關係模式的運算元的類型不可賦值給將要調用的運算子的參數時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為關係模式中的運算元 (0
) 是 int
,但 C
中定義的 >
運算子預期類型為 C
的物件
class C {
const C();
bool operator >(C other) => true;
}
void f(C c) {
switch (c) {
case > 0:
print('positive');
}
}
常見修正方式
#如果 switch 正在使用正確的值,則變更 case 以將值與正確類型的物件比較
class C {
const C();
bool operator >(C other) => true;
}
void f(C c) {
switch (c) {
case > const C():
print('positive');
}
}
如果 switch 正在使用錯誤的值,則變更用於計算要比對的值的運算式
class C {
const C();
bool operator >(C other) => true;
int get toInt => 0;
}
void f(C c) {
switch (c.toInt) {
case > 0:
print('positive');
}
}
關係模式運算子傳回類型不可賦值給布林值
#關係模式中使用的運算子的回傳類型必須可賦值給 'bool'。
描述
#當關係模式參考到一個不產生 bool
類型值的運算子時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為關係模式 > c2
中使用的運算子 >
回傳 int
類型的值,而不是 bool
class C {
const C();
int operator >(C c) => 3;
bool operator <(C c) => false;
}
const C c2 = C();
void f(C c1) {
if (c1 case > c2) {}
}
常見修正方式
#如果有應該使用的不同運算子,則變更運算子
class C {
const C();
int operator >(C c) => 3;
bool operator <(C c) => false;
}
const C c2 = C();
void f(C c1) {
if (c1 case < c2) {}
}
如果運算子預期回傳 bool
,則更新運算子的宣告
class C {
const C();
bool operator >(C c) => true;
bool operator <(C c) => false;
}
const C c2 = C();
void f(C c1) {
if (c1 case > c2) {}
}
map_模式中的其餘元素
#映射模式不能包含 rest 模式。
描述
#當映射模式包含 rest 模式時,分析器會產生此診斷訊息。映射模式比對具有比模式中明確給出的鍵更多的鍵的映射(只要給定的鍵比對),因此 rest 模式是不必要的。
範例
#以下程式碼會產生此診斷訊息,因為映射模式包含 rest 模式
void f(Map<int, String> x) {
if (x case {0: _, ...}) {}
}
常見修正方式
#移除 rest 模式
void f(Map<int, String> x) {
if (x case {0: _}) {}
}
catch外部的_rethrow
#rethrow 必須在 catch 子句內。
描述
#當 rethrow
陳述式在 catch
子句外部時,分析器會產生此診斷訊息。rethrow
陳述式用於再次拋出捕獲的例外,但在 catch
子句外部沒有捕獲的例外。
範例
#以下程式碼會產生此診斷訊息,因為 rethrow
陳述式在 catch
子句外部
void f() {
rethrow;
}
常見修正方式
#如果您嘗試重新拋出例外,則將 rethrow
陳述式包裝在 catch
子句中
void f() {
try {
// ...
} catch (exception) {
rethrow;
}
}
如果您嘗試拋出新的例外,則將 rethrow
陳述式替換為 throw
運算式
void f() {
throw UnsupportedError('Not yet implemented');
}
產生器建構子中的傳回
#建構子無法回傳值。
描述
#當產生器建構子包含指定要回傳值的 return
陳述式時,分析器會產生此診斷訊息。產生器建構子總是回傳已建立的物件,因此無法回傳不同的物件。
範例
#以下程式碼會產生此診斷訊息,因為 return
陳述式具有運算式
class C {
C() {
return this;
}
}
常見修正方式
#如果建構子應建立新實例,則移除 return
陳述式或運算式
class C {
C();
}
如果建構子不應建立新實例,則將其轉換為工廠建構子
class C {
factory C() {
return _instance;
}
static C _instance = C._();
C._();
}
產生器中的傳回
#無法從使用 'async*' 或 'sync*' 修飾符的產生器函式回傳值。
描述
#當產生器函式(主體標記為 async*
或 sync*
的函式)使用 return
陳述式回傳值,或由於使用 =>
而隱式回傳值時,分析器會產生此診斷訊息。在任何這些情況下,它們都應該使用 yield
而不是 return
。
範例
#以下程式碼會產生此診斷訊息,因為方法 f
是產生器,並且正在使用 return
回傳值
Iterable<int> f() sync* {
return 3;
}
以下程式碼會產生此診斷訊息,因為函式 f
是產生器,並且正在隱式回傳值
Stream<int> f() async* => 3;
常見修正方式
#如果函式正在使用 =>
作為函式的主體,則將其轉換為區塊函式主體,並使用 yield
回傳值
Stream<int> f() async* {
yield 3;
}
如果方法旨在作為產生器,則使用 yield
回傳值
Iterable<int> f() sync* {
yield 3;
}
如果方法不旨在作為產生器,則從主體中移除修飾符(或者如果您要回傳 future,則使用 async
)
int f() {
return 3;
}
請勿儲存的傳回
#'{0}' 使用 'doNotStore' 註解,不應回傳,除非 '{1}' 也使用註解。
描述
#當使用 doNotStore
註解註解的值從一個沒有相同註解的方法、getter 或函式回傳時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為不應儲存調用 f
的結果,但函式 g
沒有註解來保留該語意
import 'package:meta/meta.dart';
@doNotStore
int f() => 0;
int g() => f();
常見修正方式
#如果應回傳的值是不應儲存的正確值,則使用 doNotStore
註解標記函式
import 'package:meta/meta.dart';
@doNotStore
int f() => 0;
@doNotStore
int g() => f();
否則,從函式回傳不同的值
import 'package:meta/meta.dart';
@doNotStore
int f() => 0;
int g() => 0;
無效類型的傳回
#類型為 '{0}' 的值無法從建構子 '{2}' 回傳,因為它的回傳類型為 '{1}'。
類型為 '{0}' 的值無法從函式 '{2}' 回傳,因為它的回傳類型為 '{1}'。
類型為 '{0}' 的值無法從方法 '{2}' 回傳,因為它的回傳類型為 '{1}'。
描述
#當方法或函式回傳的值的類型不可賦值給宣告的回傳類型時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 f
的回傳類型為 String
,但正在回傳 int
String f() => 3;
常見修正方式
#如果回傳類型正確,則將要回傳的值替換為正確類型的值,可能透過轉換現有值
String f() => 3.toString();
如果值正確,則變更回傳類型以符合
int f() => 3;
來自封閉項的無效類型傳回
#回傳的類型 '{0}' 無法從 '{1}' 函式回傳,這是閉包的上下文所要求的。
描述
#當回傳運算式的靜態類型不可賦值給閉包所需的回傳類型時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 f
定義為回傳 String
的函式,但賦值給它的閉包回傳 int
String Function(String) f = (s) => 3;
常見修正方式
#如果回傳類型正確,則將回傳的值替換為正確類型的值,可能透過轉換現有值
String Function(String) f = (s) => 3.toString();
沒有值的傳回
#在 'return' 後面缺少回傳值。
描述
#當分析器在宣告了回傳類型的函式中找到沒有運算式的 return
陳述式時,會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為函式 f
預期回傳 int
,但沒有回傳任何值
int f() {
return;
}
常見修正方式
#新增一個計算要回傳的值的運算式
int f() {
return 0;
}
從核心匯出的_sdk_版本_async
#類別 '{0}' 在 2.1 版之前未從 'dart:core' 匯出,但此程式碼必須能夠在更早版本上執行。
描述
#當在 SDK 約束的下限小於 2.1.0 的程式碼中,在未匯入 dart:async
的程式庫中參考類別 Future
或 Stream
時,分析器會產生此診斷訊息。在早期版本中,這些類別未在 dart:core
中定義,因此匯入是必要的。
範例
#以下是一個 pubspec 的範例,它定義了一個 SDK 約束,其下限小於 2.1.0
environment:
sdk: '>=2.0.0 <2.4.0'
在具有該 pubspec 的套件中,如下程式碼會產生此診斷訊息
void f(Future f) {}
常見修正方式
#如果您不需要支援舊版本的 SDK,則可以提高 SDK 約束以允許參考類別
environment:
sdk: '>=2.1.0 <2.4.0'
如果您需要支援舊版本的 SDK,則匯入 dart:async
程式庫。
import 'dart:async';
void f(Future f) {}
const_情境中作為運算式的_sdk_版本
#在常數運算式中使用 as 運算式在 2.3.2 版之前不受支援,但此程式碼必須能夠在更早版本上執行。
描述
#當在 SDK 約束的下限小於 2.3.2 的程式碼中,在 常數上下文內找到 as
運算式時,分析器會產生此診斷訊息。在 常數上下文中使用 as
運算式在早期版本中不受支援,因此此程式碼將無法在早期版本的 SDK 上執行。
範例
#以下是一個 pubspec 的範例,它定義了一個 SDK 約束,其下限小於 2.3.2
environment:
sdk: '>=2.1.0 <2.4.0'
在具有該 pubspec 的套件中,如下程式碼會產生此診斷訊息
const num n = 3;
const int i = n as int;
常見修正方式
#如果您不需要支援舊版本的 SDK,則可以提高 SDK 約束以允許使用運算式
environment:
sdk: '>=2.3.2 <2.4.0'
如果您需要支援舊版本的 SDK,則重寫程式碼以不使用 as
運算式,或變更程式碼,使 as
運算式不在 常數上下文中
num x = 3;
int y = x as int;
const_情境中的_sdk_版本布林運算子
#在常數上下文中,對 'bool' 運算元使用運算子 '{0}' 在 2.3.2 版之前不受支援,但此程式碼必須能夠在更早版本上執行。
描述
#當在 SDK 約束的下限小於 2.3.2 的程式碼中,在 常數上下文內找到對類別 bool
使用 &
、|
或 ^
運算子的任何情況時,分析器會產生此診斷訊息。在 常數上下文中使用這些運算子在早期版本中不受支援,因此此程式碼將無法在早期版本的 SDK 上執行。
範例
#以下是一個 pubspec 的範例,它定義了一個 SDK 約束,其下限小於 2.3.2
environment:
sdk: '>=2.1.0 <2.4.0'
在具有該 pubspec 的套件中,如下程式碼會產生此診斷訊息
const bool a = true;
const bool b = false;
const bool c = a & b;
常見修正方式
#如果您不需要支援舊版本的 SDK,則可以提高 SDK 約束以允許使用運算子
environment:
sdk: '>=2.3.2 <2.4.0'
如果您需要支援舊版本的 SDK,則重寫程式碼以不使用這些運算子,或變更程式碼,使運算式不在 常數上下文中
const bool a = true;
const bool b = false;
bool c = a & b;
sdk_版本建構子拆解
#撕裂建構子需要 'constructor-tearoffs' 語言功能。
描述
#當在 SDK 約束的下限小於 2.15 的程式碼中找到建構子撕裂時,分析器會產生此診斷訊息。建構子撕裂在早期版本中不受支援,因此此程式碼將無法在早期版本的 SDK 上執行。
範例
#以下是一個 pubspec 的範例,它定義了一個 SDK 約束,其下限小於 2.15
environment:
sdk: '>=2.9.0 <2.15.0'
在具有該 pubspec 的套件中,如下程式碼會產生此診斷訊息
var setConstructor = Set.identity;
常見修正方式
#如果您不需要支援舊版本的 SDK,則可以提高 SDK 約束以允許使用運算子
environment:
sdk: '>=2.15.0 <2.16.0'
如果您需要支援舊版本的 SDK,則重寫程式碼以不使用建構子撕裂
var setConstructor = () => Set.identity();
const_情境中的_sdk_版本_eq_eq運算子
#對於非原始類型使用運算子 '==' 在 2.3.2 版之前不受支援,但此程式碼必須能夠在更早版本上執行。
描述
#當在 SDK 約束的下限小於 2.3.2 的程式碼中,在 常數上下文內找到對非原始類型使用運算子 ==
時,分析器會產生此診斷訊息。在 常數上下文中使用此運算子在早期版本中不受支援,因此此程式碼將無法在早期版本的 SDK 上執行。
範例
#以下是一個 pubspec 的範例,它定義了一個 SDK 約束,其下限小於 2.3.2
environment:
sdk: '>=2.1.0 <2.4.0'
在具有該 pubspec 的套件中,如下程式碼會產生此診斷訊息
class C {}
const C a = null;
const C b = null;
const bool same = a == b;
常見修正方式
#如果您不需要支援舊版本的 SDK,則可以提高 SDK 約束以允許使用運算子
environment:
sdk: '>=2.3.2 <2.4.0'
如果您需要支援舊版本的 SDK,則重寫程式碼以不使用 ==
運算子,或變更程式碼,使運算式不在 常數上下文中
class C {}
const C a = null;
const C b = null;
bool same = a == b;
sdk_版本擴充功能方法
#擴充方法直到 2.6.0 版本才開始支援,但這段程式碼需要在更早的版本上也能執行。
描述
#當在 SDK 約束條件的下限低於 2.6.0 的程式碼中,發現擴充宣告或擴充覆寫時,分析器會產生此診斷訊息。由於更早的版本不支援擴充方法,因此這段程式碼將無法在更早版本的 SDK 上執行。
範例
#以下範例 pubspec 定義了 SDK 約束條件,其下限低於 2.6.0
environment:
sdk: '>=2.4.0 <2.7.0'
在具有該 pubspec 的套件中,如下程式碼會產生此診斷訊息
extension E on String {
void sayHello() {
print('Hello $this');
}
}
常見修正方式
#如果您不需要支援舊版 SDK,則可以提高 SDK 約束條件,以允許使用此語法
environment:
sdk: '>=2.6.0 <2.7.0'
如果您需要支援舊版 SDK,則請重寫程式碼,使其不使用擴充方法。最常見的做法是將擴充方法的成員重寫為頂層函式(或方法),並將原本會繫結到 this
的值作為參數傳遞。
void sayHello(String s) {
print('Hello $s');
}
sdk_版本_gt_gt_gt運算子
#運算子 '>>>
' 直到 2.14.0 版本才開始支援,但這段程式碼需要在更早的版本上也能執行。
描述
#當在 SDK 約束條件的下限低於 2.14.0 的程式碼中,使用運算子 >>>
時,分析器會產生此診斷訊息。由於更早的版本不支援此運算子,因此這段程式碼將無法在更早版本的 SDK 上執行。
範例
#以下範例 pubspec 定義了 SDK 約束條件,其下限低於 2.14.0
environment:
sdk: '>=2.0.0 <2.15.0'
在具有該 pubspec 的套件中,如下程式碼會產生此診斷訊息
int x = 3 >>> 4;
常見修正方式
#如果您不需要支援舊版本的 SDK,則可以提高 SDK 約束以允許使用運算子
environment:
sdk: '>=2.14.0 <2.15.0'
如果您需要支援舊版 SDK,則請重寫程式碼,使其不使用 >>>
運算子
int x = logicalShiftRight(3, 4);
int logicalShiftRight(int leftOperand, int rightOperand) {
int divisor = 1 << rightOperand;
if (divisor == 0) {
return 0;
}
return leftOperand ~/ divisor;
}
const_情境中的_sdk_版本_is運算式
#在常數環境中使用 is
運算式直到 2.3.2 版本才開始支援,但這段程式碼需要在更早的版本上也能執行。
描述
#當在 SDK 約束條件的下限低於 2.3.2 的程式碼中,發現 常數環境 內的 is
運算式時,分析器會產生此診斷訊息。由於更早的版本不支援在 常數環境 中使用 is
運算式,因此這段程式碼將無法在更早版本的 SDK 上執行。
範例
#以下是一個 pubspec 的範例,它定義了一個 SDK 約束,其下限小於 2.3.2
environment:
sdk: '>=2.1.0 <2.4.0'
在具有該 pubspec 的套件中,如下程式碼會產生此診斷訊息
const Object x = 4;
const y = x is int ? 0 : 1;
常見修正方式
#如果您不需要支援舊版本的 SDK,則可以提高 SDK 約束以允許使用運算式
environment:
sdk: '>=2.3.2 <2.4.0'
如果您需要支援舊版 SDK,則可以重寫程式碼,使其不使用 is
運算子;或者,如果不可行,則變更程式碼,使 is
運算式不在 常數環境 中。
const Object x = 4;
var y = x is int ? 0 : 1;
sdk_版本_never
#類型 'Never' 直到 2.12.0 版本才開始支援,但這段程式碼需要在更早的版本上也能執行。
描述
#當在 SDK 約束條件的下限低於 2.12.0 的程式碼中,發現對類別 Never
的參考時,分析器會產生此診斷訊息。由於更早的版本未定義此類別,因此這段程式碼將無法在更早版本的 SDK 上執行。
範例
#以下範例 pubspec 定義了 SDK 約束條件,其下限低於 2.12.0
environment:
sdk: '>=2.5.0 <2.6.0'
在具有該 pubspec 的套件中,如下程式碼會產生此診斷訊息
Never n;
常見修正方式
#如果您不需要支援舊版 SDK,則可以提高 SDK 約束條件,以允許使用此類型
environment:
sdk: '>=2.12.0 <2.13.0'
如果您需要支援舊版 SDK,則請重寫程式碼,使其不參考此類別
dynamic x;
sdk_版本_set_字面值
#Set 字面值直到 2.2 版本才開始支援,但這段程式碼需要在更早的版本上也能執行。
描述
#當在 SDK 約束條件的下限低於 2.2.0 的程式碼中,發現 set 字面值時,分析器會產生此診斷訊息。由於更早的版本不支援 set 字面值,因此這段程式碼將無法在更早版本的 SDK 上執行。
範例
#以下範例 pubspec 定義了 SDK 約束條件,其下限低於 2.2.0
environment:
sdk: '>=2.1.0 <2.4.0'
在具有該 pubspec 的套件中,如下程式碼會產生此診斷訊息
var s = <int>{};
常見修正方式
#如果您不需要支援舊版 SDK,則可以提高 SDK 約束條件,以允許使用此語法
environment:
sdk: '>=2.2.0 <2.4.0'
如果您確實需要支援舊版 SDK,則請將 set 字面值替換為不使用字面值來建立 set 的程式碼
var s = new Set<int>();
sdk_版本_UI作為程式碼
#for、if 和 spread 元素直到 2.3.0 版本才開始支援,但這段程式碼需要在更早的版本上也能執行。
描述
#當在 SDK 約束條件的下限低於 2.3.0 的程式碼中,發現 for、if 或 spread 元素時,分析器會產生此診斷訊息。由於更早的版本不支援使用 for、if 或 spread 元素,因此這段程式碼將無法在更早版本的 SDK 上執行。
範例
#以下範例 pubspec 定義了 SDK 約束條件,其下限低於 2.3.0
environment:
sdk: '>=2.2.0 <2.4.0'
在具有該 pubspec 的套件中,如下程式碼會產生此診斷訊息
var digits = [for (int i = 0; i < 10; i++) i];
常見修正方式
#如果您不需要支援舊版 SDK,則可以提高 SDK 約束條件,以允許使用此語法
environment:
sdk: '>=2.3.0 <2.4.0'
如果您需要支援舊版 SDK,則請重寫程式碼,使其不使用這些元素
var digits = _initializeDigits();
List<int> _initializeDigits() {
var digits = <int>[];
for (int i = 0; i < 10; i++) {
digits.add(i);
}
return digits;
}
const_情境中的_sdk_版本_UI作為程式碼
#if 和 spread 元素直到 2.5.0 版本才開始在常數運算式中支援,但這段程式碼需要在更早的版本上也能執行。
描述
#當在 SDK 約束條件的下限低於 2.5.0 的程式碼中,發現 常數環境 內的 if 或 spread 元素時,分析器會產生此診斷訊息。由於更早的版本不支援在 常數環境 中使用 if 或 spread 元素,因此這段程式碼將無法在更早版本的 SDK 上執行。
範例
#以下範例 pubspec 定義了 SDK 約束條件,其下限低於 2.5.0
environment:
sdk: '>=2.4.0 <2.6.0'
在具有該 pubspec 的套件中,如下程式碼會產生此診斷訊息
const a = [1, 2];
const b = [...a];
常見修正方式
#如果您不需要支援舊版 SDK,則可以提高 SDK 約束條件,以允許使用此語法
environment:
sdk: '>=2.5.0 <2.6.0'
如果您需要支援舊版 SDK,則請重寫程式碼,使其不使用這些元素
const a = [1, 2];
const b = [1, 2];
如果不可行,則變更程式碼,使該元素不在 常數環境 中。
const a = [1, 2];
var b = [...a];
set_元素類型不可賦值
#元素類型 '{0}' 無法指派給 set 類型 '{1}'。
描述
#當 set 字面值中的元素類型無法指派給 set 的元素類型時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為字串字面值 '0'
的類型為 String
,無法指派給 int
,也就是 set 的元素類型。
var s = <int>{'0'};
常見修正方式
#如果 set 字面值的元素類型錯誤,則請變更 set 的元素類型
var s = <String>{'0'};
如果元素的類型錯誤,則請變更元素
var s = <int>{'0'.length};
共用的延遲載入前置詞
#延遲匯入的前綴詞不能用於其他匯入指示詞。
描述
#當延遲匯入中的前綴詞也用於其他匯入(無論是否延遲)作為前綴詞時,分析器會產生此診斷訊息。延遲匯入中的前綴詞不能與其他匯入共用,因為前綴詞用於載入匯入的程式庫。
範例
#以下程式碼會產生此診斷訊息,因為前綴詞 x
用於延遲匯入的前綴詞,也用於另一個匯入。
import 'dart:math' deferred as x;
import 'dart:convert' as x;
var y = x.json.encode(x.min(0, 1));
常見修正方式
#如果您可以使用不同的名稱作為延遲匯入,請這樣做
import 'dart:math' deferred as math;
import 'dart:convert' as x;
var y = x.json.encode(math.min(0, 1));
如果您可以使用不同的名稱作為其他匯入,請這樣做
import 'dart:math' deferred as x;
import 'dart:convert' as convert;
var y = convert.json.encode(x.min(0, 1));
大小註解維度
#'Array' 必須具有符合維度的 'Array' 註解。
描述
#當 Array
註解中指定的維度數量與欄位類型指定的巢狀陣列數量不符時,分析器會產生此診斷訊息。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼會產生此診斷訊息,因為欄位 a0
的類型具有三個巢狀陣列,但在 Array
註解中僅給定兩個維度。
import 'dart:ffi';
final class C extends Struct {
@Array(8, 8)
external Array<Array<Array<Uint8>>> a0;
}
常見修正方式
#如果欄位的類型正確,則請修正註解以使其具有所需的維度數量
import 'dart:ffi';
final class C extends Struct {
@Array(8, 8, 4)
external Array<Array<Array<Uint8>>> a0;
}
如果欄位的類型錯誤,則請修正欄位的類型
import 'dart:ffi';
final class C extends Struct {
@Array(8, 8)
external Array<Array<Uint8>> a0;
}
靜態存取實例成員
#無法使用靜態存取來存取實例成員 '{0}'。
描述
#當使用類別名稱來存取實例欄位時,分析器會產生此診斷訊息。實例欄位不存在於類別上;它們僅存在於類別的實例上。
範例
#以下程式碼會產生此診斷訊息,因為 x
是一個實例欄位。
class C {
static int a = 0;
int b = 0;
}
int f() => C.b;
常見修正方式
#如果您打算存取靜態欄位,則請將欄位名稱變更為現有的靜態欄位
class C {
static int a = 0;
int b = 0;
}
int f() => C.a;
如果您打算存取實例欄位,則請使用類別的實例來存取欄位
class C {
static int a = 0;
int b = 0;
}
int f(C c) => c.b;
base或_final的子類型不是_base、final或_sealed
#mixin '{0}' 必須為 'base',因為超類型 '{1}' 為 'base'。
mixin '{0}' 必須為 'base',因為超類型 '{1}' 為 'final'。
類型 '{0}' 必須為 'base'、'final' 或 'sealed',因為超類型 '{1}' 為 'base'。
類型 '{0}' 必須為 'base'、'final' 或 'sealed',因為超類型 '{1}' 為 'final'。
描述
#當類別或 mixin 具有直接或間接的超類型為 base
或 final
,但該類別或 mixin 本身未標記為 base
、final
或 sealed
時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為類別 B
是 A
的子類型,而 A
是 base
類別,但 B
既不是 base
、final
也不是 sealed
。
base class A {}
class B extends A {}
常見修正方式
#將 base
、final
或 sealed
新增至類別或 mixin 宣告中
base class A {}
final class B extends A {}
延遲載入類別的子類型
#類別和 mixin 無法實作延遲類別。
類別無法擴展延遲類別。
類別無法混入延遲類別。
描述
#當類型(類別或 mixin)是使用延遲匯入匯入的程式庫中的類別的子類型時,分析器會產生此診斷訊息。類型的超類型必須與類型同時編譯,而延遲程式庫中的類別要等到程式庫載入後才會編譯。
有關更多資訊,請查看 延遲載入程式庫。
範例
#假設檔案 a.dart
定義了類別 A
class A {}
以下程式碼會產生此診斷訊息,因為 B
的超類別是在延遲程式庫中宣告的。
import 'a.dart' deferred as a;
class B extends a.A {}
常見修正方式
#如果您需要建立延遲程式庫中類型的子類型,則請移除 deferred
關鍵字
import 'a.dart' as a;
class B extends a.A {}
不允許類型的子類型
#'{0}' 無法用作超類別約束。
類別和 mixin 無法實作 '{0}'。
類別無法擴展 '{0}'。
類別無法混入 '{0}'。
描述
#當限制類別之一用於 extends
、implements
、with
或 on
子句中時,分析器會產生此診斷訊息。類別 bool
、double
、FutureOr
、int
、Null
、num
和 String
都以此方式受到限制,以實現更有效率的實作。
範例
#以下程式碼會產生此診斷訊息,因為 String
用於 extends
子句中。
class A extends String {}
以下程式碼會產生此診斷訊息,因為 String
用於 implements
子句中。
class B implements String {}
以下程式碼會產生此診斷訊息,因為 String
用於 with
子句中。
class C with String {}
以下程式碼會產生此診斷訊息,因為 String
用於 on
子句中。
mixin M on String {}
常見修正方式
#如果應指定不同的類型,則請替換該類型
class A extends Object {}
如果沒有其他合適的類型,則移除該類型,並可能移除整個子句
class B {}
ffi_類別的子類型
#類別 '{0}' 無法擴展 '{1}'。
類別 '{0}' 無法實作 '{1}'。
類別 '{0}' 無法混入 '{1}'。
描述
#當類別擴展任何 FFI 類別(Struct
或 Union
除外),或實作或混入任何 FFI 類別時,分析器會產生此診斷訊息。Struct
和 Union
是唯一可以作為子類型的 FFI 類別,並且只能透過擴展它們來作為子類型。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼會產生此診斷訊息,因為類別 C
擴展了 Double
。
import 'dart:ffi';
final class C extends Double {}
常見修正方式
#如果類別應擴展 Struct
或 Union
,則請變更類別的宣告
import 'dart:ffi';
final class C extends Struct {
@Int32()
external int i;
}
如果類別不應擴展 Struct
或 Union
,則請移除對 FFI 類別的任何參考
final class C {}
sealed_類別的子類型
#類別 '{0}' 不應被擴展、混入或實作,因為它是 sealed 類別。
描述
#當 sealed 類別(具有 sealed
註解或繼承或混入 sealed 類別的類別)在類別或 mixin 宣告的 extends
、implements
或 with
子句中被參考,且該宣告與 sealed 類別不在同一個套件中時,分析器會產生此診斷訊息。
範例
#假設一個套件中的程式庫(非正在分析的套件)包含以下內容:
import 'package:meta/meta.dart';
class A {}
@sealed
class B {}
以下程式碼會產生此診斷訊息,因為 C
(與 B
不在同一個套件中)正在擴展 sealed 類別 B
。
import 'package:a/a.dart';
class C extends B {}
常見修正方式
#如果類別不需要成為 sealed 類別的子類型,則請變更宣告,使其不是子類型
import 'package:a/a.dart';
class B extends A {}
如果類別需要成為 sealed 類別的子類型,則請變更 sealed 類別,使其不再是 sealed 類別,或將子類別移至與 sealed 類別相同的套件中。
struct_類別的子類型
#類別 '{0}' 無法擴展 '{1}',因為 '{1}' 是 'Struct'、'Union' 或 'AbiSpecificInteger' 的子類型。
類別 '{0}' 無法實作 '{1}',因為 '{1}' 是 'Struct'、'Union' 或 'AbiSpecificInteger' 的子類型。
類別 '{0}' 無法混入 '{1}',因為 '{1}' 是 'Struct'、'Union' 或 'AbiSpecificInteger' 的子類型。
描述
#當類別擴展、實作或混入擴展 Struct
或 Union
的類別時,分析器會產生此診斷訊息。類別只能直接擴展 Struct
或 Union
。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼會產生此診斷訊息,因為類別 C
擴展了 S
,而 S
擴展了 Struct
。
import 'dart:ffi';
final class S extends Struct {
external Pointer f;
}
final class C extends S {
external Pointer g;
}
常見修正方式
#如果您嘗試定義一個 struct 或 union,其與不同的 struct 或 union 共用某些宣告的欄位,則請直接擴展 Struct
或 Union
並複製共用欄位
import 'dart:ffi';
final class S extends Struct {
external Pointer f;
}
final class C extends Struct {
external Pointer f;
external Pointer g;
}
超類型展開為類型參數
#擴展為類型參數的類型別名無法被實作。
擴展為類型參數的類型別名無法被混入。
擴展為類型參數的類型別名無法用作超類別約束。
擴展為類型參數的類型別名無法用作超類別。
描述
#當擴展為類型參數的類型別名用於 extends
、implements
、with
或 on
子句中時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為擴展為類型參數 S
的類型別名 T
用於類別 C
的 extends
子句中。
typedef T<S> = S;
class C extends T<Object> {}
常見修正方式
#直接使用類型引數的值
typedef T<S> = S;
class C extends Object {}
super_形式參數類型不是關聯項的子類型
#此參數的類型 '{0}' 不是相關聯的超建構子參數的類型 '{1}' 的子類型。
描述
#當超參數的類型不是超建構子中對應參數的子類型時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為類別 B
的建構子中超參數 x
的類型不是類別 A
的建構子中參數 x
的子類型。
class A {
A(num x);
}
class B extends A {
B(String super.x);
}
常見修正方式
#如果超參數的類型可以與超建構子的參數相同,則請從超參數中移除類型註解(如果類型是隱含的,則會從超建構子中的類型推斷出來)
class A {
A(num x);
}
class B extends A {
B(super.x);
}
如果超參數的類型可以是相應參數類型之子類型,則請變更超參數的類型
class A {
A(num x);
}
class B extends A {
B(int super.x);
}
如果超參數的類型無法變更,則請使用一般參數而不是超參數
class A {
A(num x);
}
class B extends A {
B(String x) : super(x.length);
}
沒有關聯具名的_super_形式參數
#沒有相關聯的具名超建構子參數。
描述
#當建構子中存在具名超參數,而隱含或明確調用的超建構子沒有同名的具名參數時,分析器會產生此診斷訊息。
具名超參數會依名稱與超建構子中的具名參數相關聯。
範例
#以下程式碼會產生此診斷訊息,因為 A
中的建構子沒有名為 y
的參數。
class A {
A({int? x});
}
class B extends A {
B({super.y});
}
常見修正方式
#如果超參數應與超建構子中現有的參數相關聯,則請變更名稱以符合對應參數的名稱
class A {
A({int? x});
}
class B extends A {
B({super.x});
}
如果超參數應與尚未新增至超建構子的參數相關聯,則請新增該參數
class A {
A({int? x, int? y});
}
class B extends A {
B({super.y});
}
如果超參數不對應於超建構子的具名參數,則請將其變更為一般參數
class A {
A({int? x});
}
class B extends A {
B({int? y});
}
沒有關聯位置的_super_形式參數
#沒有相關聯的位置超建構子參數。
描述
#當建構子中存在位置超參數,而隱含或明確調用的超建構子在對應索引處沒有位置參數時,分析器會產生此診斷訊息。
位置超參數會依索引與超建構子中的位置參數相關聯。也就是說,第一個超參數與超建構子中的第一個位置參數相關聯,第二個與第二個相關聯,依此類推。
範例
#以下程式碼會產生此診斷訊息,因為 B
中的建構子具有位置超參數,但 A
中的超建構子中沒有位置參數。
class A {
A({int? x});
}
class B extends A {
B(super.x);
}
以下程式碼會產生此診斷訊息,因為 B
中的建構子具有兩個位置超參數,但 A
中的超建構子中只有一個位置參數,這表示 y
沒有對應的參數。
class A {
A(int x);
}
class B extends A {
B(super.x, super.y);
}
常見修正方式
#如果超建構子應具有對應於超參數的位置參數,則請適當地更新超建構子
class A {
A(int x, int y);
}
class B extends A {
B(super.x, super.y);
}
如果超建構子正確或無法變更,則請將超參數轉換為一般參數
class A {
A(int x);
}
class B extends A {
B(super.x, int y);
}
super_調用不是最後一個
#invalid_super_invocation
)
超建構子呼叫必須是初始化列表中的最後一個項目:'{0}'。
描述
#當建構子的初始化列表包含對超類別中建構子的調用,但該調用不是初始化列表中的最後一個項目時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為對超類別建構子的調用不是初始化列表中的最後一個項目。
class A {
A(int x);
}
class B extends A {
B(int x) : super(x), assert(x >= 0);
}
常見修正方式
#將對超類別建構子的調用移至初始化列表的末尾
class A {
A(int x);
}
class B extends A {
B(int x) : assert(x >= 0), super(x);
}
列舉建構子中的_super
#列舉建構子不能有 'super' 初始化子。
描述
#當列舉中的建構子的初始化列表包含對超建構子的調用時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為列舉 E
中的建構子在初始化列表中具有超建構子調用。
enum E {
e;
const E() : super();
}
常見修正方式
#移除超建構子調用
enum E {
e;
const E();
}
擴充功能中的_super
#'super' 關鍵字不能在擴充方法中使用,因為擴充方法沒有超類別。
描述
#當在擴充方法內宣告的成員使用 super
關鍵字時,分析器會產生此診斷訊息。擴充方法不是類別,也沒有超類別,因此 super
關鍵字沒有任何用途。
範例
#以下程式碼會產生此診斷訊息,因為 super
不能在擴充方法中使用。
extension E on Object {
String get displayString => super.toString();
}
常見修正方式
#移除 super
關鍵字
extension E on Object {
String get displayString => toString();
}
擴充功能類型中的_super
#'super' 關鍵字不能在擴充類型中使用,因為擴充類型沒有超類別。
描述
#當 super
用於擴充類型的實例成員中時,分析器會產生此診斷訊息。擴充類型沒有超類別,因此沒有可以調用的繼承成員。
範例
#以下程式碼會產生此診斷訊息,因為
extension type E(String s) {
void m() {
super.m();
}
}
常見修正方式
#替換或移除 super
調用
extension type E(String s) {
void m() {
s.toLowerCase();
}
}
無效情境中的_super
#'super' 調用的上下文無效。
描述
#當關鍵字 super
在實例方法之外使用時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 super
用於頂層函式中。
void f() {
super.f();
}
常見修正方式
#重寫程式碼,使其不使用 super
。
重新導向建構子中的_super
#重新導向的建構子不能有 'super' 初始化子。
描述
#當重新導向到另一個建構子的建構子也嘗試調用超類別的建構子時,分析器會產生此診斷訊息。當調用重新導向建構子所重新導向的建構子時,將會調用超類別建構子。
範例
#以下程式碼會產生此診斷訊息,因為建構子 C.a
同時重新導向到 C.b
並調用超類別的建構子。
class C {
C.a() : this.b(), super();
C.b();
}
常見修正方式
#移除 super
建構子的調用
class C {
C.a() : this.b();
C.b();
}
switch_case正常完成
#'case' 不應正常完成。
描述
#當 switch
語句中 case
標籤後的語句可能 fall through 到下一個 case
或 default
標籤時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為值為零 (0
) 的 case
標籤 fall through 到 default
語句。
void f(int a) {
switch (a) {
case 0:
print(0);
default:
return;
}
}
常見修正方式
#變更控制流程,使 case
不會 fall through。有多種方法可以做到這一點,包括在目前語句列表的末尾新增以下其中一項:
return
語句、throw
運算式、break
語句、continue
或- 傳回類型為
Never
的函式或方法的調用。
switch_運算式不可賦值
#switch 運算式的類型 '{0}' 無法指派給 case 運算式的類型 '{1}'。
描述
#當 switch
語句中運算式的類型無法指派給 case
子句中運算式的類型時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 s
的類型 (String
) 無法指派給 0
的類型 (int
)。
void f(String s) {
switch (s) {
case 0:
break;
}
}
常見修正方式
#如果 case
運算式的類型正確,則請變更 switch
語句中的運算式以使其具有正確的類型
void f(String s) {
switch (int.parse(s)) {
case 0:
break;
}
}
如果 switch
運算式的類型正確,則請變更 case
運算式以使其具有正確的類型
void f(String s) {
switch (s) {
case '0':
break;
}
}
抽象類別的產生器建構子的拆解
#抽象類別的產生器建構子無法被 tear off。
描述
#當從抽象類別 tear off 產生器建構子時,分析器會產生此診斷訊息。這是不允許的,因為建立抽象類別的實例是無效的,這表示 tear off 的建構子沒有任何有效的用途。
範例
#以下程式碼會產生此診斷訊息,因為正在 tear off 建構子 C.new
,而類別 C
是一個抽象類別。
abstract class C {
C();
}
void f() {
C.new;
}
常見修正方式
#Tear off 具體類別的建構子。
註解中的文字方向碼點
#Unicode 代碼點 'U+{0}' 會變更文字的外觀,使其與編譯器解讀的方式不同。
描述
#當分析器遇到包含文字方向 Unicode 代碼點的原始碼時,會產生此診斷訊息。這些代碼點會導致字串字面值或註解中的原始碼以不同於編輯器中顯示的方式進行解讀和編譯,從而導致可能的安全性漏洞。
範例
#以下程式碼會產生兩次此診斷訊息,因為標籤字串的開頭和結尾都有隱藏字元。
var label = 'Interactive text';
常見修正方式
#如果代碼點旨在包含在字串字面值中,則請逸出它們
var label = '\u202AInteractive text\u202C';
如果代碼點不旨在包含在字串字面值中,則請移除它們
var label = 'Interactive text';
字面值中的文字方向碼點
#Unicode 代碼點 'U+{0}' 會變更文字的外觀,使其與編譯器解讀的方式不同。
描述
#當分析器遇到包含文字方向 Unicode 代碼點的原始碼時,會產生此診斷訊息。這些代碼點會導致字串字面值或註解中的原始碼以不同於編輯器中顯示的方式進行解讀和編譯,從而導致可能的安全性漏洞。
範例
#以下程式碼會產生兩次此診斷訊息,因為標籤字串的開頭和結尾都有隱藏字元。
var label = 'Interactive text';
常見修正方式
#如果代碼點旨在包含在字串字面值中,則請逸出它們
var label = '\u202AInteractive text\u202C';
如果代碼點不旨在包含在字串字面值中,則請移除它們
var label = 'Interactive text';
無效類型的拋出
#拋出運算式的類型 '{0}' 必須可指派給 'Object'。
描述
#當 throw 運算式中運算式的類型無法指派給 Object
時,分析器會產生此診斷訊息。拋出 null
是無效的,因此使用可能評估為 null
的運算式也是無效的。
範例
#以下程式碼會產生此診斷訊息,因為 s
可能為 null
。
void f(String? s) {
throw s;
}
常見修正方式
#為運算式新增明確的 null 檢查
void f(String? s) {
throw s!;
}
最上層循環
#無法推斷 '{0}' 的類型,因為它透過循環 {1} 依賴於自身。
描述
#當頂層變數沒有類型註解,且變數的初始化器直接或間接地參考該變數時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為變數 x
和 y
是根據彼此定義的,並且兩者都沒有明確的類型,因此無法推斷另一個的類型。
var x = y;
var y = x;
常見修正方式
#如果這兩個變數不需要互相參考,則請打破循環
var x = 0;
var y = x;
如果這兩個變數需要互相參考,則請至少為其中一個變數提供明確的類型
int x = y;
var y = x;
請注意,但是,雖然此程式碼不會產生任何診斷訊息,但除非至少其中一個變數在參考循環中的任何變數之前被指派一個不依賴於其他變數的值,否則它將在運行時產生堆疊溢位。
類型別名無法參考自身
#類型定義不能直接或透過另一個類型定義遞迴地參考自身。
描述
#當類型定義直接或間接地參考自身時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 F
透過 G
間接地依賴於自身。
typedef F = void Function(G);
typedef G = void Function(F);
常見修正方式
#變更循環中的一個或多個類型定義,使它們都不參考自身
typedef F = void Function(G);
typedef G = void Function(int);
類型註解延遲載入類別
#延遲類型 '{0}' 不能用於宣告、轉型或類型測試中。
描述
#當類型註解在變數宣告中,或在轉型 (as
) 或類型測試 (is
) 中使用的類型是從使用延遲匯入匯入的程式庫中宣告的類型時,分析器會產生此診斷訊息。這些類型需要在編譯時可用,但實際上並非如此。
有關更多資訊,請查看 延遲載入程式庫。
範例
#以下程式碼會產生此診斷訊息,因為參數 f
的類型是從延遲程式庫匯入的。
import 'dart:io' deferred as io;
void f(io.File f) {}
常見修正方式
#如果您需要參考匯入的類型,則請移除 deferred
關鍵字
import 'dart:io' as io;
void f(io.File f) {}
如果需要延遲匯入,並且有另一個合適的類型,則請使用該類型來代替延遲程式庫中的類型。
類型引數不符合界限
#'{0}' 不符合類型參數 '{1}' 的界限 '{2}'。
描述
#當類型引數與對應類型參數的界限不同或不是其子類別時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 String
不是 num
的子類別。
class A<E extends num> {}
var a = A<String>();
常見修正方式
#將類型引數變更為界限的子類別
class A<E extends num> {}
var a = A<int>();
使用_null的類型檢查
#非 null 的測試應使用 '!= null' 完成。
Null 的測試應使用 '== null' 完成。
描述
#當存在類型檢查(使用 as
運算子)且類型為 Null
時,分析器會產生此診斷訊息。只有一個值的類型為 Null
,因此當明確測試 null
時,程式碼既更具可讀性,效能也更高。
範例
#以下程式碼會產生此診斷訊息,因為程式碼正在使用類型檢查來測試 s
的值是否為 null
。
void f(String? s) {
if (s is Null) {
return;
}
print(s);
}
以下程式碼會產生此診斷訊息,因為程式碼正在使用類型檢查來測試 s
的值是否為 null
以外的內容。
void f(String? s) {
if (s is! Null) {
print(s);
}
}
常見修正方式
#將類型檢查替換為與 null
的等效比較
void f(String? s) {
if (s == null) {
return;
}
print(s);
}
靜態參考的類型參數
#靜態成員不能參考類別的類型參數。
描述
#當靜態成員參考為類別宣告的類型參數時,分析器會產生此診斷訊息。類型參數僅對類別的實例才有意義。
範例
#以下程式碼會產生此診斷訊息,因為靜態方法 hasType
參考了類型參數 T
。
class C<T> {
static bool hasType(Object o) => o is T;
}
常見修正方式
#如果成員可以是實例成員,則請移除關鍵字 static
class C<T> {
bool hasType(Object o) => o is T;
}
如果成員必須是靜態成員,則請使該成員成為泛型
class C<T> {
static bool hasType<S>(Object o) => o is S;
}
請注意,但是,T
和 S
之間沒有關係,因此第二個選項會將語義變更為可能預期的語義。
其界限的超類型的類型參數
#'{0}' 不能是其上限的超類型。
描述
#當類型參數的界限(extends
關鍵字後面的類型)直接或間接地是類型參數本身時,分析器會產生此診斷訊息。聲明類型參數必須與自身相同,或是自身的子類型,或是自身的子類型是沒有幫助的,因為它始終會與自身相同。
範例
#以下程式碼會產生此診斷訊息,因為 T
的界限為 T
。
class C<T extends T> {}
以下程式碼會產生此診斷訊息,因為 T1
的界限為 T2
,而 T2
的界限為 T1
,實際上使 T1
的界限變為 T1
。
class C<T1 extends T2, T2 extends T1> {}
常見修正方式
#如果類型參數需要成為某種類型的子類別,則請將界限替換為所需的類型
class C<T extends num> {}
如果類型參數可以是任何類型,則請移除 extends
子句
class C<T> {}
使用非類型的類型測試
#名稱 '{0}' 不是類型,不能在 'is' 運算式中使用。
描述
#當 is
或 is!
測試的右側不是類型時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為右側是參數,而不是類型。
typedef B = int Function(int);
void f(Object a, B b) {
if (a is b) {
return;
}
}
常見修正方式
#如果您打算使用類型測試,則請將右側替換為類型
typedef B = int Function(int);
void f(Object a, B b) {
if (a is B) {
return;
}
}
如果您打算使用不同類型的測試,則請變更測試
typedef B = int Function(int);
void f(Object a, B b) {
if (a == b) {
return;
}
}
使用未定義名稱的類型測試
#名稱 '{0}' 未定義,因此無法在 'is' 運算式中使用。
描述
#當類型測試運算式中 is
後面的名稱未定義時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為名稱 Srting
未定義。
void f(Object o) {
if (o is Srting) {
// ...
}
}
常見修正方式
#將名稱替換為型別的名稱。
void f(Object o) {
if (o is String) {
// ...
}
}
未檢查地使用可為 Null 值
#可為 null 的運算式不能用作條件。
可為 null 的運算式不能在 for-in 迴圈中用作迭代器。
可為 null 的運算式不能用於 spread 中。
可為 null 的運算式不能用於 yield-each 語句中。
函式不能無條件調用,因為它可能為 'null'。
方法 '{0}' 不能無條件調用,因為接收器可能為 'null'。
運算子 '{0}' 不能無條件調用,因為接收器可能為 'null'。
屬性 '{0}' 不能無條件存取,因為接收器可能為 'null'。
描述
#當 可能為非 null 的類型的運算式在未先驗證值是否為 null
的情況下被取值時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 s
在被參考的點上可能為 null
。
void f(String? s) {
if (s.length > 3) {
// ...
}
}
常見修正方式
#如果值確實可能為 null
,則請新增測試以確保僅在值不為 null
時才存取成員
void f(String? s) {
if (s != null && s.length > 3) {
// ...
}
}
如果運算式是變數,且值永遠不應為 null
,則請將變數的類型變更為不可為 null
void f(String s) {
if (s.length > 3) {
// ...
}
}
如果您認為運算式的值永遠不應為 null
,但您無法變更變數的類型,並且您願意承擔在您錯誤時在運行時拋出異常的風險,則可以斷言該值不為 null
void f(String? s) {
if (s!.length > 3) {
// ...
}
}
未定義的註解
#未定義的名稱「{0}」被用作註解。
描述
#當未定義的名稱被用作註解時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為名稱 undefined
未被定義
@undefined
void f() {}
常見修正方式
#如果名稱正確,但尚未宣告,則將該名稱宣告為常數值
const undefined = 'undefined';
@undefined
void f() {}
如果名稱錯誤,請將該名稱替換為有效的常數名稱
@deprecated
void f() {}
否則,請移除該註解。
未定義的類別
#未定義的類別「{0}」。
描述
#當分析器遇到一個看起來像是類別名稱的識別符,但該識別符未被定義或在其被引用的範圍內不可見時,會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 Piont
未被定義
class Point {}
void f(Piont p) {}
常見修正方式
#如果識別符未被定義,則定義它或將其替換為已定義的類別名稱。上述範例可以透過修正類別的拼字來更正
class Point {}
void f(Point p) {}
如果類別已定義但不可見,則您可能需要新增一個匯入。
初始化器中未定義的建構子
#類別「{0}」沒有名為「{1}」的建構子。
類別 '{0}' 沒有未命名的建構子。
描述
#當在建構子的初始化列表中呼叫超類別建構子時,但超類別未定義被呼叫的建構子,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 A
沒有未命名的建構子
class A {
A.n();
}
class B extends A {
B() : super();
}
以下程式碼會產生此診斷訊息,因為 A
沒有名為 m
的建構子
class A {
A.n();
}
class B extends A {
B() : super.m();
}
常見修正方式
#如果超類別定義了一個應該被呼叫的建構子,則變更正在呼叫的建構子
class A {
A.n();
}
class B extends A {
B() : super.n();
}
如果超類別未定義適當的建構子,則定義正在呼叫的建構子
class A {
A.m();
A.n();
}
class B extends A {
B() : super.m();
}
未定義的列舉常數
#在「{1}」中沒有名為「{0}」的常數。
描述
#當分析器遇到一個看起來像是列舉值的名稱的識別符,且該名稱未被定義或在其被引用的範圍內不可見時,會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 E
沒有定義名為 c
的常數
enum E {a, b}
var e = E.c;
常見修正方式
#如果應該定義常數,則將其新增到列舉的宣告中
enum E {a, b, c}
var e = E.c;
如果不應該定義常數,則將名稱變更為現有常數的名稱
enum E {a, b}
var e = E.b;
未定義的列舉建構子
#列舉沒有名為「{0}」的建構子。
列舉沒有未命名的建構子。
描述
#當呼叫用於初始化列舉值的建構子不存在時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為列舉值 c
正由未命名的建構子初始化,但 E
中未定義未命名的建構子
enum E {
c();
const E.x();
}
以下程式碼會產生此診斷訊息,因為列舉值 c
正由名為 x
的建構子初始化,但 E
中未定義名為 x
的建構子
enum E {
c.x();
const E.y();
}
常見修正方式
#如果列舉值正由未命名的建構子初始化,且應該使用其中一個命名的建構子,則新增建構子的名稱
enum E {
c.x();
const E.x();
}
如果列舉值正由未命名的建構子初始化,且沒有任何命名的建構子是適當的,則定義未命名的建構子
enum E {
c();
const E();
}
如果列舉值正由命名的建構子初始化,且應該使用其中一個現有的建構子,則變更正在呼叫的建構子的名稱(如果應該使用未命名的建構子,則移除它)
enum E {
c.y();
const E();
const E.y();
}
如果列舉值正由命名的建構子初始化,且沒有任何現有的建構子是適當的,則定義一個具有所使用名稱的建構子
enum E {
c.x();
const E.x();
}
未定義的擴充功能_getter
#擴充套件「{1}」未定義 getter「{0}」。
描述
#當擴充套件覆寫被用於呼叫 getter,但指定的擴充套件未定義該 getter 時,分析器會產生此診斷訊息。當參考靜態 getter 但指定的擴充套件未定義該 getter 時,分析器也會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為擴充套件 E
沒有宣告名為 b
的實例 getter
extension E on String {
String get a => 'a';
}
extension F on String {
String get b => 'b';
}
void f() {
E('c').b;
}
以下程式碼會產生此診斷訊息,因為擴充套件 E
沒有宣告名為 a
的靜態 getter
extension E on String {}
var x = E.a;
常見修正方式
#如果 getter 的名稱不正確,則將其變更為現有 getter 的名稱
extension E on String {
String get a => 'a';
}
extension F on String {
String get b => 'b';
}
void f() {
E('c').a;
}
如果 getter 的名稱正確,但擴充套件的名稱錯誤,則將擴充套件的名稱變更為正確的名稱
extension E on String {
String get a => 'a';
}
extension F on String {
String get b => 'b';
}
void f() {
F('c').b;
}
如果 getter 和擴充套件的名稱都正確,但未定義 getter,則定義 getter
extension E on String {
String get a => 'a';
String get b => 'z';
}
extension F on String {
String get b => 'b';
}
void f() {
E('c').b;
}
未定義的擴充功能方法
#擴充套件「{1}」未定義方法「{0}」。
描述
#當擴充套件覆寫被用於呼叫方法,但指定的擴充套件未定義該方法時,分析器會產生此診斷訊息。當參考靜態方法但指定的擴充套件未定義該方法時,分析器也會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為擴充套件 E
沒有宣告名為 b
的實例方法
extension E on String {
String a() => 'a';
}
extension F on String {
String b() => 'b';
}
void f() {
E('c').b();
}
以下程式碼會產生此診斷訊息,因為擴充套件 E
沒有宣告名為 a
的靜態方法
extension E on String {}
var x = E.a();
常見修正方式
#如果方法的名稱不正確,則將其變更為現有方法的名稱
extension E on String {
String a() => 'a';
}
extension F on String {
String b() => 'b';
}
void f() {
E('c').a();
}
如果方法的名稱正確,但擴充套件的名稱錯誤,則將擴充套件的名稱變更為正確的名稱
extension E on String {
String a() => 'a';
}
extension F on String {
String b() => 'b';
}
void f() {
F('c').b();
}
如果方法和擴充套件的名稱都正確,但未定義方法,則定義方法
extension E on String {
String a() => 'a';
String b() => 'z';
}
extension F on String {
String b() => 'b';
}
void f() {
E('c').b();
}
未定義的擴充功能運算子
#擴充套件「{1}」未定義運算子「{0}」。
描述
#當在特定擴充套件上呼叫運算子,但該擴充套件未實作該運算子時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為擴充套件 E
未定義運算子 *
var x = E('') * 4;
extension E on String {}
常見修正方式
#如果預期擴充套件實作該運算子,則將該運算子的實作新增到擴充套件
var x = E('') * 4;
extension E on String {
int operator *(int multiplier) => length * multiplier;
}
如果運算子由不同的擴充套件定義,則將擴充套件的名稱變更為定義該運算子的擴充套件的名稱。
如果運算子在擴充套件覆寫的引數上定義,則移除擴充套件覆寫
var x = '' * 4;
extension E on String {}
未定義的擴充功能_setter
#擴充套件「{1}」未定義 setter「{0}」。
描述
#當擴充套件覆寫被用於呼叫 setter,但指定的擴充套件未定義該 setter 時,分析器會產生此診斷訊息。當參考靜態 setter 但指定的擴充套件未定義該 setter 時,分析器也會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為擴充套件 E
沒有宣告名為 b
的實例 setter
extension E on String {
set a(String v) {}
}
extension F on String {
set b(String v) {}
}
void f() {
E('c').b = 'd';
}
以下程式碼會產生此診斷訊息,因為擴充套件 E
沒有宣告名為 a
的靜態 setter
extension E on String {}
void f() {
E.a = 3;
}
常見修正方式
#如果 setter 的名稱不正確,則將其變更為現有 setter 的名稱
extension E on String {
set a(String v) {}
}
extension F on String {
set b(String v) {}
}
void f() {
E('c').a = 'd';
}
如果 setter 的名稱正確,但擴充套件的名稱錯誤,則將擴充套件的名稱變更為正確的名稱
extension E on String {
set a(String v) {}
}
extension F on String {
set b(String v) {}
}
void f() {
F('c').b = 'd';
}
如果 setter 和擴充套件的名稱都正確,但未定義 setter,則定義 setter
extension E on String {
set a(String v) {}
set b(String v) {}
}
extension F on String {
set b(String v) {}
}
void f() {
E('c').b = 'd';
}
未定義的函式
#未定義函式「{0}」。
描述
#當分析器遇到一個看起來像是函式名稱的識別符,但該識別符未被定義或在其被引用的範圍內不可見時,會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為名稱 emty
未被定義
List<int> empty() => [];
void main() {
print(emty());
}
常見修正方式
#如果識別符未被定義,則定義它或將其替換為已定義的函式名稱。上述範例可以透過修正函式的拼字來更正
List<int> empty() => [];
void main() {
print(empty());
}
如果函式已定義但不可見,則您可能需要新增一個匯入或重新安排您的程式碼以使函式可見。
未定義的_getter
#getter「{0}」未針對「{1}」函式類型定義。
getter「{0}」未針對類型「{1}」定義。
描述
#當分析器遇到一個看起來像是 getter 名稱的識別符,但該識別符未被定義或在其被引用的範圍內不可見時,會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 String
沒有名為 len
的成員
int f(String s) => s.len;
常見修正方式
#如果識別符未被定義,則定義它或將其替換為已定義的 getter 名稱。上述範例可以透過修正 getter 的拼字來更正
int f(String s) => s.length;
未定義的隱藏名稱
#程式庫「{0}」沒有匯出具有隱藏名稱「{1}」的成員。
描述
#當 hide 組合器包含一個未由正在匯入的程式庫定義的名稱時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 dart:math
沒有定義名稱 String
import 'dart:math' hide String, max;
var x = min(0, 1);
常見修正方式
#如果應該隱藏不同的名稱,則更正名稱。否則,從清單中移除該名稱
import 'dart:math' hide max;
var x = min(0, 1);
未定義的識別項
#未定義的名稱「{0}」。
描述
#當分析器遇到一個未被定義或在其被引用的範圍內不可見的識別符時,會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為名稱 rihgt
未被定義
int min(int left, int right) => left <= rihgt ? left : right;
常見修正方式
#如果識別符未被定義,則定義它或將其替換為已定義的識別符。上述範例可以透過修正變數的拼字來更正
int min(int left, int right) => left <= right ? left : right;
如果識別符已定義但不可見,則您可能需要新增一個匯入或重新安排您的程式碼以使識別符可見。
未定義的識別項_await
#未標記 'async' 的函式主體中使用了未定義的名稱 'await'。
描述
#當在方法或函式主體中使用名稱 await
而未宣告,且主體未標記 async
關鍵字時,分析器會產生此診斷訊息。名稱 await
僅在非同步函式中引入 await 運算式。
範例
#以下程式碼會產生此診斷訊息,因為名稱 await
在 f
的主體中使用,即使 f
的主體未標記 async
關鍵字
void f(p) { await p; }
常見修正方式
#將關鍵字 async
新增到函式主體
void f(p) async { await p; }
未定義的方法
#方法「{0}」未針對「{1}」函式類型定義。
方法「{0}」未針對類型「{1}」定義。
描述
#當分析器遇到一個看起來像是方法名稱的識別符,但該識別符未被定義或在其被引用的範圍內不可見時,會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為識別符 removeMiddle
未被定義
int f(List<int> l) => l.removeMiddle();
常見修正方式
#如果識別符未被定義,則定義它或將其替換為已定義的方法名稱。上述範例可以透過修正方法的拼字來更正
int f(List<int> l) => l.removeLast();
未定義的具名參數
#未定義具名參數「{0}」。
描述
#當方法或函式調用具有具名引數,但被調用的方法或函式未定義具有相同名稱的參數時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 m
沒有宣告名為 a
的具名參數
class C {
m({int? b}) {}
}
void f(C c) {
c.m(a: 1);
}
常見修正方式
#如果引數名稱拼寫錯誤,則將其替換為正確的名稱。上述範例可以透過將 a
變更為 b
來修正
class C {
m({int? b}) {}
}
void f(C c) {
c.m(b: 1);
}
如果子類別新增了一個具有問題名稱的參數,則將接收器轉換為子類別
class C {
m({int? b}) {}
}
class D extends C {
m({int? a, int? b}) {}
}
void f(C c) {
(c as D).m(a: 1);
}
如果應該將參數新增到函式,則新增它
class C {
m({int? a, int? b}) {}
}
void f(C c) {
c.m(a: 1);
}
未定義的運算子
#運算子「{0}」未針對類型「{1}」定義。
描述
#當在未定義運算子的物件上調用使用者可定義的運算子時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為類別 C
未定義運算子 +
class C {}
C f(C c) => c + 2;
常見修正方式
#如果應該為類別定義運算子,則定義它
class C {
C operator +(int i) => this;
}
C f(C c) => c + 2;
未定義的前置詞名稱
#名稱「{0}」正透過前綴「{1}」被參考,但它未在任何使用該前綴匯入的程式庫中定義。
描述
#當找到帶有前綴的識別符,且前綴有效,但該識別符未在任何使用該前綴匯入的程式庫中宣告時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 dart:core
沒有定義任何名為 a
的內容
import 'dart:core' as p;
void f() {
p.a;
}
常見修正方式
#如果宣告名稱的程式庫尚未匯入,則為該程式庫新增一個匯入。
如果名稱錯誤,則將其變更為在匯入的程式庫中宣告的名稱之一。
未定義的參考參數
#參數「{0}」未由「{1}」定義。
描述
#當 UseResult.unless(parameterDefined: parameterName)
形式的註解指定一個未由帶註解的函式定義的參數名稱時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為函式 f
沒有名為 b
的參數
import 'package:meta/meta.dart';
@UseResult.unless(parameterDefined: 'b')
int f([int? a]) => a ?? 0;
常見修正方式
#變更名為 parameterDefined
的引數以符合函式的其中一個參數的名稱
import 'package:meta/meta.dart';
@UseResult.unless(parameterDefined: 'a')
int f([int? a]) => a ?? 0;
未定義的_setter
#setter「{0}」未針對「{1}」函式類型定義。
setter「{0}」未針對類型「{1}」定義。
描述
#當分析器遇到一個看起來像是 setter 名稱的識別符,但該識別符未被定義或在其被引用的範圍內不可見時,會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為沒有名為 z
的 setter
class C {
int x = 0;
void m(int y) {
this.z = y;
}
}
常見修正方式
#如果識別符未被定義,則定義它或將其替換為已定義的 setter 名稱。上述範例可以透過修正 setter 的拼字來更正
class C {
int x = 0;
void m(int y) {
this.x = y;
}
}
未定義的顯示名稱
#程式庫「{0}」沒有匯出具有顯示名稱「{1}」的成員。
描述
#當 show 組合器包含一個未由正在匯入的程式庫定義的名稱時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 dart:math
沒有定義名稱 String
import 'dart:math' show min, String;
var x = min(0, 1);
常見修正方式
#如果應該顯示不同的名稱,則更正名稱。否則,從清單中移除該名稱
import 'dart:math' show min;
var x = min(0, 1);
未定義的_super_成員
#undefined_super_method
)
getter「{0}」未在「{1}」的超類別中定義。
方法「{0}」未在「{1}」的超類別中定義。
運算子「{0}」未在「{1}」的超類別中定義。
setter「{0}」未在「{1}」的超類別中定義。
描述
#當使用 super
參考繼承的成員(方法、getter、setter 或運算子),但在超類別鏈中沒有具有該名稱的成員時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 Object
沒有定義名為 n
的方法
class C {
void m() {
super.n();
}
}
以下程式碼會產生此診斷訊息,因為 Object
沒有定義名為 g
的 getter
class C {
void m() {
super.g;
}
}
常見修正方式
#如果您打算調用的繼承成員具有不同的名稱,則使調用的成員的名稱與繼承成員的名稱相符。
如果您打算調用的成員在同一個類別中定義,則移除 super.
。
如果未定義成員,則將成員新增到其中一個超類別或移除調用。
未知的平台
#平台「{0}」不是可辨識的平台。
描述
#當在 platforms
映射中使用未知的平台名稱作為鍵時,分析器會產生此診斷訊息。若要進一步瞭解如何指定套件支援的平台,請查看關於平台宣告的文件。
範例
#以下 pubspec.yaml
會產生此診斷訊息,因為平台 browser
是未知的。
name: example
platforms:
browser:
常見修正方式
#如果您可以依賴自動平台偵測,則省略最上層的 platforms
鍵。
name: example
如果您需要手動指定支援平台的清單,則將 platforms
欄位寫為以已知平台名稱作為鍵的映射。
name: example
platforms:
# These are the known platforms
android:
ios:
linux:
macos:
web:
windows:
不必要的轉換
#不必要的轉型。
描述
#當要轉換的值已知已為要轉換成的類型時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為由於 is
測試,n
已知為 int
void f(num n) {
if (n is int) {
(n as int).isEven;
}
}
常見修正方式
#移除不必要的轉換。
void f(num n) {
if (n is int) {
n.isEven;
}
}
不必要的開發相依性
#在 {0} 上的開發相依性是不必要的,因為在該套件上也有正常的相依性。
描述
#當 dev_dependencies
下有一個條目,用於也列在 dependencies
下的套件時,分析器會產生此診斷訊息。dependencies
下的套件可用於套件中的所有程式碼,因此不需要也將它們列在 dev_dependencies
下。
範例
#以下程式碼會產生此診斷訊息,因為套件 meta
同時列在 dependencies
和 dev_dependencies
下
name: example
dependencies:
meta: ^1.0.2
dev_dependencies:
meta: ^1.0.2
常見修正方式
#移除 dev_dependencies
下的條目(如果那是唯一列出的套件,則移除 dev_dependencies
鍵)
name: example
dependencies:
meta: ^1.0.2
不必要的_final
#關鍵字 'final' 是不必要的,因為參數隱含地是 'final'。
描述
#當建構子中的欄位初始化參數或超參數具有關鍵字 final
時,分析器會產生此診斷訊息。在這兩種情況下,關鍵字都是不必要的,因為參數隱含地是 final
。
範例
#以下程式碼會產生此診斷訊息,因為欄位初始化參數具有關鍵字 final
class A {
int value;
A(final this.value);
}
以下程式碼會產生此診斷訊息,因為 B
中的超參數具有關鍵字 final
class A {
A(int value);
}
class B extends A {
B(final super.value);
}
常見修正方式
#移除不必要的 final
關鍵字
class A {
A(int value);
}
class B extends A {
B(super.value);
}
不必要的匯入
#匯入 '{0}' 是不必要的,因為所有使用的元素也由匯入 '{1}' 提供。
描述
#當不需要匯入時,分析器會產生此診斷訊息,因為所有匯入且在匯入程式庫中被參考的名稱也透過另一個匯入可見。
範例
#給定一個包含以下內容的檔案 a.dart
class A {}
並且,給定一個包含以下內容的檔案 b.dart
export 'a.dart';
class B {}
以下程式碼會產生此診斷訊息,因為從 a.dart
匯入的類別 A
也從 b.dart
匯入。移除匯入 a.dart
不會改變語意
import 'a.dart';
import 'b.dart';
void f(A a, B b) {}
常見修正方式
#如果不需要匯入,則移除它。
如果此匯入所匯入的某些名稱打算使用但尚未被使用,並且如果這些名稱未由其他匯入匯入,則新增對這些名稱的遺失參考。
不必要的_NaN比較
#double 無法等於 'double.nan',因此條件永遠為 'false'。
double 無法等於 'double.nan',因此條件永遠為 'true'。
描述
#當使用 ==
或 !=
將值與 double.nan
比較時,分析器會產生此診斷訊息。
Dart 遵循 IEEE 754 浮點標準,用於浮點運算的語意,該標準指出,對於任何浮點值 x
(包括 NaN、正無限和負無限),
NaN == x
永遠為 falseNaN != x
永遠為 true
因此,將任何值與 NaN 比較是沒有意義的,因為結果已經已知(基於所使用的比較運算子)。
範例
#以下程式碼會產生此診斷訊息,因為 d
正與 double.nan
比較
bool isNaN(double d) => d == double.nan;
常見修正方式
#改用 getter double.isNaN
bool isNaN(double d) => d.isNaN;
不必要的非空值斷言
#'!' 將不起作用,因為接收器不能為 null。
描述
#當 !
運算子的運算元不能為 null
時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷,因為 x
不可為 null
int f(int x) {
return x!;
}
常見修正方式
#移除 null 檢查運算子 (!
)
int f(int x) {
return x;
}
不必要的_noSuchMethod
#不必要的 'noSuchMethod' 宣告。
描述
#當存在 noSuchMethod
的宣告,而宣告唯一做的事情是調用覆寫的宣告,且覆寫的宣告不是 Object
中的宣告時,分析器會產生此診斷訊息。
覆寫 Object
的 noSuchMethod
的實作(無論實作做什麼)向分析器發出訊號,表明它不應標記任何未在該類別中實作的繼承抽象方法。即使覆寫的實作是從超類別繼承的,這也有效,因此在子類別中再次宣告它沒有價值。
範例
#以下程式碼會產生此診斷訊息,因為 A
中的 noSuchMethod
宣告使 B
中的 noSuchMethod
宣告變得不必要
class A {
@override
dynamic noSuchMethod(x) => super.noSuchMethod(x);
}
class B extends A {
@override
dynamic noSuchMethod(y) {
return super.noSuchMethod(y);
}
}
常見修正方式
#移除不必要的宣告
class A {
@override
dynamic noSuchMethod(x) => super.noSuchMethod(x);
}
class B extends A {}
不必要的_null_斷言模式
#null-assert 模式將不起作用,因為比對的類型不可為 null。
描述
#當 null-assert 模式用於比對不可為 null 的值時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為變數 x
不可為 null
void f(int x) {
if (x case var a! when a > 0) {}
}
常見修正方式
#移除 null-assert 模式
void f(int x) {
if (x case var a when a > 0) {}
}
不必要的_null_檢查模式
#null-check 模式將不起作用,因為比對的類型不可為 null。
描述
#當 null-check 模式用於比對不可為 null 的值時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為值 x
不可為 null
void f(int x) {
if (x case var a? when a > 0) {}
}
常見修正方式
#移除 null-check 模式
void f(int x) {
if (x case var a when a > 0) {}
}
不必要的_null比較
#運算元不能為 'null',因此條件永遠為 'false'。
運算元不能為 'null',因此條件永遠為 'true'。
運算元必須為 'null',因此條件永遠為 'false'。
運算元必須為 'null',因此條件永遠為 'true'。
描述
#當分析器找到一個與 null
進行等式比較(==
或 !=
),且另一個運算元不能為 null
時,會產生此診斷訊息。這樣的比較始終為 true
或 false
,因此它們沒有任何意義。
範例
#以下程式碼會產生此診斷訊息,因為 x
永遠不能為 null
,因此比較始終評估為 true
void f(int x) {
if (x != null) {
print(x);
}
}
以下程式碼會產生此診斷訊息,因為 x
永遠不能為 null
,因此比較始終評估為 false
void f(int x) {
if (x == null) {
throw ArgumentError("x can't be null");
}
}
常見修正方式
#如果另一個運算元應該能夠為 null
,則變更運算元的類型
void f(int? x) {
if (x != null) {
print(x);
}
}
如果另一個運算元確實不能為 null
,則移除條件
void f(int x) {
print(x);
}
不必要的問號
#'?' 是不必要的,因為沒有它,「{0}」也是可為 null 的。
描述
#當類型 dynamic
或類型 Null
後面跟著問號時,分析器會產生此診斷訊息。這兩種類型本身都是可為 null 的,因此問號不會改變語意。
範例
#以下程式碼會產生此診斷訊息,因為 dynamic
後面的問號是不必要的
dynamic? x;
常見修正方式
#移除不必要的問號
dynamic x;
不必要的_set_字面值
#大括號不必要地將此運算式包裝在集合字面值中。
描述
#當具有 void
、Future<void>
或 FutureOr<void>
回傳類型的函式使用運算式函式主體 (=>
) 且回傳值是包含單一元素的字面值集合時,分析器會產生此診斷訊息。
雖然語言允許,但從 void
函式回傳值是沒有用的,因為它不能在呼叫點使用。在這種特定情況下,回傳通常是由於對語法的誤解。大括號是不必要的,可以移除。
範例
#以下程式碼會產生此診斷訊息,因為傳遞給 g
的閉包的回傳類型為 void
,但正在回傳一個集合
void f() {
g(() => {1});
}
void g(void Function() p) {}
常見修正方式
#從值周圍移除大括號
void f() {
g(() => 1);
}
void g(void Function() p) {}
不必要的類型檢查
#不必要的類型檢查;結果永遠為 'false'。
不必要的類型檢查;結果永遠為 'true'。
描述
#當類型檢查的值(使用 is
或 is!
)在編譯時已知時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為測試 a is Object?
永遠為 true
bool f<T>(T a) => a is Object?;
常見修正方式
#如果類型檢查未檢查您打算檢查的內容,則變更測試
bool f<T>(T a) => a is Object;
如果類型檢查確實檢查了您打算檢查的內容,則將類型檢查替換為其已知值或完全移除它
bool f<T>(T a) => true;
對非本機靜態成員的不合格參考
#來自超類型的靜態成員必須以定義類型的名稱限定。
描述
#當一個類別中的程式碼參考超類別中的靜態成員,而沒有在成員名稱前加上超類別的名稱時,分析器會產生此診斷訊息。靜態成員只能在宣告它們的類別中無前綴地被參考。
範例
#以下程式碼會產生此診斷訊息,因為靜態欄位 x
在 getter g
中被參考,而沒有在其前面加上定義類別的名稱
class A {
static int x = 3;
}
class B extends A {
int get g => x;
}
常見修正方式
#在靜態成員的名稱前加上宣告類別的名稱
class A {
static int x = 3;
}
class B extends A {
int get g => A.x;
}
對擴充類型靜態成員的不合格參考
#來自擴充類型或其超類別之一的靜態成員必須以定義類型的名稱限定。
描述
#當找到未定義的名稱,且該名稱與擴充類型或其超類別之一的靜態成員相同時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 m
是擴充類型 C
的靜態成員
class C {
static void m() {}
}
extension E on C {
void f() {
m();
}
}
常見修正方式
#如果您嘗試參考在擴充套件外部宣告的靜態成員,則在成員的參考之前新增類別或擴充套件的名稱
class C {
static void m() {}
}
extension E on C {
void f() {
C.m();
}
}
如果您正在參考尚未宣告的成員,則新增宣告
class C {
static void m() {}
}
extension E on C {
void f() {
m();
}
void m() {}
}
無法連線的_switch_case
#此情況已包含在先前的案例中。
描述
#當 switch
語句中的 case
子句不比對任何內容,因為所有可比對的值都已由較早的 case
子句比對時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為值 1
已在前一個案例中比對
void f(int x) {
switch (x) {
case 1:
print('one');
case 1:
print('two');
}
}
常見修正方式
#變更其中一個或兩個衝突的案例以比對不同的值
void f(int x) {
switch (x) {
case 1:
print('one');
case 2:
print('two');
}
}
無法連線的_switch_default
#此 default 子句已包含在先前的案例中。
描述
#當 switch
語句中的 default
子句不比對任何內容,因為所有可比對的值都已由較早的 case
子句比對時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為值 E.e1
和 E.e2
已在前述案例中比對
enum E { e1, e2 }
void f(E x) {
switch (x) {
case E.e1:
print('one');
case E.e2:
print('two');
default:
print('other');
}
}
常見修正方式
#移除不必要的 default
子句
enum E { e1, e2 }
void f(E x) {
switch (x) {
case E.e1:
print('one');
case E.e2:
print('two');
}
}
未使用的_catch_子句
#例外變數「{0}」未使用,因此可以移除 'catch' 子句。
描述
#當找到 catch
子句,且異常參數和可選的堆疊追蹤參數都未在 catch
區塊中使用時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 e
未被參考
void f() {
try {
int.parse(';');
} on FormatException catch (e) {
// ignored
}
}
常見修正方式
#移除未使用的 catch
子句
void f() {
try {
int.parse(';');
} on FormatException {
// ignored
}
}
未使用的_catch堆疊
#堆疊追蹤變數「{0}」未使用,可以移除。
描述
#當 catch
子句中的堆疊追蹤參數未在 catch
區塊的主體中被參考時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 stackTrace
未被參考
void f() {
try {
// ...
} catch (exception, stackTrace) {
// ...
}
}
常見修正方式
#如果您需要參考堆疊追蹤參數,則新增對它的參考。否則,移除它
void f() {
try {
// ...
} catch (exception) {
// ...
}
}
未使用的元素
#宣告「{0}」未被參考。
描述
#當私有宣告未在其包含宣告的程式庫中被參考時,分析器會產生此診斷訊息。分析以下幾種宣告
- 私有最上層宣告及其所有成員
- 公有宣告的私有成員
並非所有對元素的參考都會將其標記為「已使用」
- 為最上層變數賦值(使用標準
=
賦值或可為 null 的??=
賦值)不計為使用它。 - 在文件註解參考中參考元素不計為使用它。
- 在
is
運算式右側參考類別、mixin 或列舉不計為使用它。
範例
#假設程式庫中沒有程式碼參考 _C
,以下程式碼會產生此診斷訊息
class _C {}
常見修正方式
#如果不需要宣告,則移除它。
如果宣告的目的是被使用,則新增程式碼以使用它。
未使用的元素參數
#永遠不會為可選參數「{0}」提供值。
描述
#當永遠不會為私有宣告中宣告的可選參數傳遞值時,分析器會產生此診斷訊息。
範例
#假設程式庫中沒有程式碼在任何 _m
的調用中為 y
傳遞值,以下程式碼會產生此診斷訊息
class C {
void _m(int x, [int? y]) {}
void n() => _m(0);
}
常見修正方式
#如果不需要宣告,則移除它
class C {
void _m(int x) {}
void n() => _m(0);
}
如果宣告的目的是被使用,則新增程式碼以使用它。
未使用的欄位
#未使用欄位「{0}」的值。
描述
#當宣告了私有欄位但從未讀取,即使它在一個或多個位置被寫入時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為欄位 _originalValue
在程式庫中的任何地方都未被讀取
class C {
final String _originalValue;
final String _currentValue;
C(this._originalValue) : _currentValue = _originalValue;
String get value => _currentValue;
}
看起來欄位 _originalValue
正在初始化器中被讀取 (_currentValue = _originalValue
),但那實際上是對同名參數的參考,而不是對欄位的參考。
常見修正方式
#如果不需要欄位,則移除它。
如果欄位的目的是被使用,則新增遺失的程式碼。
未使用的匯入
#未使用的匯入:「{0}」。
描述
#當不需要匯入時,分析器會產生此診斷訊息,因為沒有任何匯入的名稱在匯入程式庫中被參考。
範例
#以下程式碼會產生此診斷訊息,因為在程式庫中沒有參考 dart:async
中定義的任何內容
import 'dart:async';
void main() {}
常見修正方式
#如果不需要匯入,則移除它。
如果打算使用某些匯入的名稱,則新增遺失的程式碼。
未使用的標籤
#標籤「{0}」未使用。
描述
#當找到未使用的標籤時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為標籤 loop
未在方法中的任何地方被參考
void f(int limit) {
loop: for (int i = 0; i < limit; i++) {
print(i);
}
}
常見修正方式
#如果不需要標籤,則移除它
void f(int limit) {
for (int i = 0; i < limit; i++) {
print(i);
}
}
如果需要標籤,則使用它
void f(int limit) {
loop: for (int i = 0; i < limit; i++) {
print(i);
if (i != 0) {
break loop;
}
}
}
未使用的區域變數
#未使用區域變數「{0}」的值。
描述
#當宣告了區域變數但從未讀取,即使它在一個或多個位置被寫入時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 count
的值從未被讀取
void main() {
int count = 0;
}
常見修正方式
#如果不需要變數,則移除它。
如果變數的目的是被使用,則新增遺失的程式碼。
未使用的結果
#應該使用「{0}」。{1}。
應該使用「{0}」的值。
描述
#當調用了使用 useResult
註解的函式,且未使用該函式回傳的值時,分析器會產生此診斷訊息。如果調用了值的成員、如果值傳遞給另一個函式,或者如果值賦值給變數或欄位,則該值被視為已使用。
範例
#以下程式碼會產生此診斷訊息,因為 c.a()
的調用未使用,即使方法 a
使用 useResult
註解
import 'package:meta/meta.dart';
class C {
@useResult
int a() => 0;
int b() => 0;
}
void f(C c) {
c.a();
}
常見修正方式
#如果您打算調用帶註解的函式,則使用回傳的值
import 'package:meta/meta.dart';
class C {
@useResult
int a() => 0;
int b() => 0;
}
void f(C c) {
print(c.a());
}
如果您打算調用不同的函式,則更正正在調用的函式名稱
import 'package:meta/meta.dart';
class C {
@useResult
int a() => 0;
int b() => 0;
}
void f(C c) {
c.b();
}
未使用的顯示名稱
#名稱 {0} 已顯示,但未使用。
描述
#當 show 組合器包含一個未在程式庫中使用的名稱時,分析器會產生此診斷訊息。因為它未被參考,所以可以移除該名稱。
範例
#以下程式碼會產生此診斷訊息,因為函式 max
未被使用
import 'dart:math' show min, max;
var x = min(0, 1);
常見修正方式
#使用該名稱或移除它
import 'dart:math' show min;
var x = min(0, 1);
URI不存在
#URI 的目標不存在:「{0}」。
描述
#當找到 import、export 或 part 指令,且 URI 指向不存在的檔案時,分析器會產生此診斷訊息。
範例
#如果檔案 lib.dart
不存在,則以下程式碼會產生此診斷訊息
import 'lib.dart';
常見修正方式
#如果 URI 拼寫錯誤或無效,則更正 URI。
如果 URI 正確,則建立檔案。
文件匯入中_URI不存在
#URI 的目標不存在:「{0}」。
描述
#當找到 doc-import,且 URI 指向不存在的檔案時,分析器會產生此診斷訊息。
範例
#如果檔案 lib.dart
不存在,則以下程式碼會產生此診斷訊息
/// @docImport 'lib.dart';
library;
常見修正方式
#如果 URI 拼寫錯誤或無效,則更正 URI。
如果 URI 正確,則建立檔案。
URI尚未產生
#URI 的目標尚未產生:「{0}」。
描述
#當找到 import、export 或 part 指令,且 URI 指向不存在的檔案,且檔案名稱以程式碼產生器常用的模式結尾時,分析器會產生此診斷訊息,例如以下之一
.g.dart
.pb.dart
.pbenum.dart
.pbserver.dart
.pbjson.dart
.template.dart
範例
#如果 lib.g.dart
檔案不存在,以下程式碼會產生此診斷訊息
import 'lib.g.dart';
常見修正方式
#如果檔案是產生出來的檔案,那麼請執行產生該檔案的產生器。
如果檔案不是產生出來的檔案,那麼請檢查 URI 的拼寫或建立檔案。
具有內插的_URI
#URI 不能使用字串插值。
描述
#當 import
、export
或 part
指令中的字串字面值包含插值時,分析器會產生此診斷訊息。指令中 URI 的解析必須在宣告編譯之前發生,因此在決定 URI 的值時無法評估表達式。
範例
#以下程式碼會產生此診斷訊息,因為 import
指令中的字串包含插值
import 'dart:$m';
const m = 'math';
常見修正方式
#從 URI 中移除插值
import 'dart:math';
var zero = min(0, 0);
原生擴充功能的使用
#Dart 原生擴充功能已棄用,且在 Dart 2.15 中不可用。
描述
#當使用 dart-ext
方案匯入程式庫時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為原生程式庫 x
正使用 dart-ext
方案匯入
import 'dart-ext:x';
常見修正方式
#重寫程式碼以使用 dart:ffi
作為呼叫原生程式庫內容的方式。
void結果的使用
#此表達式的類型為 'void',因此其值無法使用。
描述
#當分析器找到類型為 void
的表達式,且該表達式用在期望值的地方時 (例如在成員存取之前或賦值運算子的右側),就會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 f
沒有產生可以呼叫 toString
的物件
void f() {}
void g() {
f().toString();
}
常見修正方式
#可以重寫程式碼,使表達式具有值,或者重寫程式碼,使其不依賴該值。
列舉中的值宣告
#名為 'values' 的成員不能在列舉中宣告。
描述
#當列舉宣告定義名為 values
的成員時 (無論該成員是列舉值、實例成員或靜態成員),分析器會產生此診斷訊息。
任何此類成員都會與靜態 getter values
的隱式宣告衝突,後者會傳回包含所有列舉常數的列表。
範例
#以下程式碼會產生此診斷訊息,因為列舉 E
定義了名為 values
的實例成員
enum E {
v;
void values() {}
}
常見修正方式
#變更衝突成員的名稱
enum E {
v;
void getValues() {}
}
變長陣列不是最後一個
#變長 'Array' 只能作為 Structs 的最後一個欄位出現。
描述
#當變長內聯 Array
不是 Struct
的最後一個成員時,分析器會產生此診斷訊息。
有關 FFI 的更多資訊,請參閱 使用 dart:ffi 的 C 互操作。
範例
#以下程式碼會產生此診斷訊息,因為欄位 a0
的類型具有三個巢狀陣列,但在 Array
註解中僅給定兩個維度。
import 'dart:ffi';
final class C extends Struct {
@Array.variable()
external Array<Uint8> a0;
@Uint8()
external int a1;
}
常見修正方式
#將變長內聯 Array
移動到 struct 中的最後一個欄位。
import 'dart:ffi';
final class C extends Struct {
@Uint8()
external int a1;
@Array.variable()
external Array<Uint8> a0;
}
如果內聯陣列具有固定大小,請使用大小來註解它
import 'dart:ffi';
final class C extends Struct {
@Array(10)
external Array<Uint8> a0;
@Uint8()
external int a1;
}
宣告情境中的變數模式關鍵字
#宣告上下文中的變數模式不能指定 'var' 或 'final' 關鍵字。
描述
#當在宣告上下文中使用變數模式時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為記錄模式中的變數模式位於宣告上下文中
void f((int, int) r) {
var (var x, y) = r;
print(x + y);
}
常見修正方式
#移除變數模式中的 var
或 final
關鍵字。
void f((int, int) r) {
var (x, y) = r;
print(x + y);
}
變數類型不符
#類型為 '{0}' 的值無法賦值給類型為 '{1}' 的 const 變數。
描述
#當常數表達式的求值會導致 CastException
時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 x
的值是 int
,無法賦值給 y
,因為 int
不是 String
const dynamic x = 0;
const String y = x;
常見修正方式
#如果常數的宣告是正確的,那麼將賦值的值更改為正確的類型。
const dynamic x = 0;
const String y = '$x';
如果賦值的值是正確的,那麼更改宣告以具有正確的類型。
const int x = 0;
const int y = x;
工作區欄位不是清單
#'workspace' 欄位的值必須是相對檔案路徑的列表。
描述
#當 workspace
鍵的值不是列表時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為當期望是列表時,workspace
鍵的值卻是字串
name: example
workspace: notPaths
常見修正方式
#更改 workspace 欄位的值,使其成為列表。
name: example
workspace:
- pkg/package_1
- pkg/package_2
工作區值不是字串
#Workspace 條目必須是目錄路徑 (字串)。
描述
#當 workspace
列表包含不是字串的值時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 workspace
列表包含一個 map
name: example
workspace:
- image.gif: true
常見修正方式
#更改 workspace
列表,使其僅包含有效的 POSIX 樣式目錄路徑。
name: example
workspace:
- pkg/package_1
- pkg/package_2
工作區值不是子目錄
#Workspace 值必須是 '{0}' 子目錄的相對路徑。
描述
#當 workspace
列表包含的值不是包含 `pubspec.yaml` 檔案的目錄的子目錄時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 workspace
列表中的值不是包含 'pubspec.yaml' 檔案的目錄的子目錄的相對路徑
name: example
workspace:
- /home/my_package
常見修正方式
#更改 workspace
列表,使其僅包含子目錄路徑。
name: example
workspace:
- pkg/package_1
- pkg/package_2
運算子的參數數量錯誤
#運算子 '-' 應該宣告 0 或 1 個參數,但找到 {0} 個。
運算子 '{0}' 應該宣告正好 {1} 個參數,但找到 {2} 個。
描述
#當運算子的宣告具有錯誤的參數數量時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為運算子 +
必須有一個對應於右運算元的單一參數
class C {
int operator +(a, b) => 0;
}
常見修正方式
#新增或移除參數以符合所需的數量。
class C {
int operator +(a) => 0;
}
setter的參數數量錯誤
#Setter 必須宣告正好一個必要的位置參數。
描述
#當找到未宣告正好一個必要位置參數的 setter 時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 setter s
宣告了兩個必要參數
class C {
set s(int x, int y) {}
}
以下程式碼會產生此診斷訊息,因為 setter s
宣告了一個可選參數
class C {
set s([int? x]) {}
}
常見修正方式
#更改宣告,使其正好有一個必要的位置參數。
class C {
set s(int x) {}
}
類型引數數量錯誤
#類型 '{0}' 宣告了 {1} 個類型參數,但給定了 {2} 個類型引數。
描述
#當使用具有類型參數的類型並提供類型引數時,但類型引數的數量與類型參數的數量不同時,分析器會產生此診斷訊息。
當調用建構子且類型引數的數量與為類別宣告的類型參數的數量不符時,分析器也會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 C
有一個類型參數,但在用作類型註解時卻提供了兩個類型引數
class C<E> {}
void f(C<int, int> x) {}
以下程式碼會產生此診斷訊息,因為 C
宣告了一個類型參數,但在建立實例時卻提供了兩個類型引數
class C<E> {}
var c = C<int, int>();
常見修正方式
#根據需要新增或移除類型引數,以符合為類型定義的類型參數的數量。
class C<E> {}
void f(C<int> x) {}
建構子的類型引數數量錯誤
#建構子 '{0}.{1}' 沒有類型參數。
描述
#當在具名建構子的名稱後提供類型引數時,分析器會產生此診斷訊息。建構子無法宣告類型參數,因此調用只能提供與類別相關聯的類型引數,並且這些類型引數必須跟在類別名稱之後,而不是建構子名稱之後。
範例
#以下程式碼會產生此診斷訊息,因為類型參數 (<String>
) 跟在建構子名稱之後,而不是類別名稱之後
class C<T> {
C.named();
}
C f() => C.named<String>();
常見修正方式
#如果類型引數是用於類別的類型參數,那麼將類型引數移動到類別名稱之後。
class C<T> {
C.named();
}
C f() => C<String>.named();
如果類型引數不是用於類別的類型參數,那麼移除它們。
class C<T> {
C.named();
}
C f() => C.named();
列舉的類型引數數量錯誤
#列舉宣告了 {0} 個類型參數,但給定了 {1} 個類型引數。
描述
#當實例化具有類型參數的列舉中的列舉值並提供類型引數時,但類型引數的數量與類型參數的數量不同時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為列舉值 c
提供了一個類型引數,即使列舉 E
被宣告為具有兩個類型參數
enum E<T, U> {
c<int>()
}
常見修正方式
#如果類型參數的數量是正確的,那麼更改類型引數的數量以符合類型參數的數量。
enum E<T, U> {
c<int, String>()
}
如果類型引數的數量是正確的,那麼更改類型參數的數量以符合類型引數的數量。
enum E<T> {
c<int>()
}
擴充功能的類型引數數量錯誤
#擴充功能 '{0}' 宣告了 {1} 個類型參數,但給定了 {2} 個類型引數。
描述
#當使用具有類型參數的擴充功能並提供類型引數時,但類型引數的數量與類型參數的數量不同時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為擴充功能 E
被宣告為具有單一類型參數 (`T`),但擴充功能覆寫卻有兩個類型引數
extension E<T> on List<T> {
int get len => length;
}
void f(List<int> p) {
E<int, String>(p).len;
}
常見修正方式
#更改類型引數,使類型引數的數量與類型參數的數量相同。
extension E<T> on List<T> {
int get len => length;
}
void f(List<int> p) {
E<int>(p).len;
}
方法的類型引數數量錯誤
#方法 '{0}' 宣告了 {1} 個類型參數,但給定了 {2} 個類型引數。
描述
#當調用方法或函式時,類型引數的數量與其宣告中指定的類型參數的數量不同時,分析器會產生此診斷訊息。必須沒有類型引數,或者引數的數量必須與參數的數量相符。
範例
#以下程式碼會產生此診斷訊息,因為方法 `m` 的調用具有兩個類型引數,但 `m` 的宣告僅有一個類型參數
class C {
int m<A>(A a) => 0;
}
int f(C c) => c.m<int, int>(2);
常見修正方式
#如果類型引數是必要的,那麼通過新增或移除類型引數使其符合類型參數的數量。
class C {
int m<A>(A a) => 0;
}
int f(C c) => c.m<int>(2);
如果類型引數不是必要的,那麼移除它們。
class C {
int m<A>(A a) => 0;
}
int f(C c) => c.m(2);
非產生器中的_yield
#Yield 語句必須在產生器函式中 (標記為 'async*' 或 'sync*' 的函式)。
Yield-each 語句必須在產生器函式中 (標記為 'async*' 或 'sync*' 的函式)。
描述
#當 `yield` 或 `yield*` 語句出現在主體未標記為 `async*` 或 `sync*` 修飾符之一的函式中時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 `yield` 正在主體沒有修飾符的函式中使用
Iterable<int> get digits {
yield* [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
}
以下程式碼會產生此診斷訊息,因為 `yield*` 正在主體具有 `async` 修飾符而不是 `async*` 修飾符的函式中使用
Stream<int> get digits async {
yield* [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
}
常見修正方式
#新增修飾符,或將現有的修飾符更改為 `async*` 或 `sync*`。
Iterable<int> get digits sync* {
yield* [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
}
無效類型的_yield
#類型為 '{0}' 的 yielded 值必須可賦值給 '{1}'。
'yield*' 表達式所暗示的類型 '{0}' 必須可賦值給 '{1}'。
描述
#當 `yield` 或 `yield*` 表達式產生的物件類型與要從產生器 (標記為 `sync*` 或 `async*` 的函式或方法) 傳回的 `Iterable` 或 `Stream` 類型傳回的物件類型不符時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 getter `zero` 被宣告為傳回一個傳回整數的 `Iterable`,但 `yield` 正從 iterable 傳回一個字串
Iterable<int> get zero sync* {
yield '0';
}
常見修正方式
#如果函式的傳回類型是正確的,那麼修正關鍵字 `yield` 後面的表達式以傳回正確的類型。
Iterable<int> get zero sync* {
yield 0;
}
如果 `yield` 後面的表達式是正確的,那麼更改函式的傳回類型以允許它。
Iterable<String> get zero sync* {
yield '0';
}
永遠宣告傳回類型
#函式 '{0}' 應該要有傳回類型,但沒有。
方法 '{0}' 應該要有傳回類型,但沒有。
描述
#當方法或函式沒有明確的傳回類型時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為函式 f
沒有傳回類型
f() {}
常見修正方式
#新增明確的傳回類型。
void f() {}
永遠將控制主體放在新行
#陳述式應該在不同的行上。
描述
#當受控制流程陳述式 (`if`、`for`、`while` 或 `do`) 控制的程式碼與控制流程陳述式在同一行時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 `return` 陳述式與控制 `return` 是否會執行的 `if` 在同一行。
void f(bool b) {
if (b) return;
}
常見修正方式
#將受控制的陳述式放在不同的、縮排的行上。
void f(bool b) {
if (b)
return;
}
永遠將必要的具名參數放在最前面
#必要的具名參數應該在可選的具名參數之前。
描述
#當必要的具名參數出現在可選的具名參數之後時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為必要的參數 x
在可選的參數 y
之後
void f({int? y, required int x}) {}
常見修正方式
#重新排序參數,使所有必要的具名參數都在任何可選的具名參數之前。
void f({required int x, int? y}) {}
永遠使用套件匯入
#對於 'lib' 目錄中的檔案,請使用 'package:' 匯入。
描述
#當 `lib` 目錄內的程式庫中的 `import` 使用相對路徑來匯入同一套件的 `lib` 目錄內的另一個程式庫時,分析器會產生此診斷訊息。
範例
#假設名為 `a.dart` 的檔案和以下程式碼都在同一套件的 `lib` 目錄內,以下程式碼會產生此診斷訊息,因為使用了相對 URI 來匯入 `a.dart`。
import 'a.dart';
常見修正方式
#使用套件匯入。
import 'package:p/a.dart';
註解覆寫
#成員 '{0}' 覆寫了繼承的成員,但未以 '@override' 註解。
描述
#當成員覆寫了繼承的成員,但未以 `@override` 註解時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為類別 `B` 中的方法 `m` 覆寫了類別 `A` 中具有相同名稱的方法,但未標記為有意覆寫
class A {
void m() {}
}
class B extends A {
void m() {}
}
常見修正方式
#如果子類別中的成員旨在覆寫超類別中的成員,那麼新增 `@override` 註解。
class A {
void m() {}
}
class B extends A {
@override
void m() {}
}
如果子類別中的成員不旨在覆寫超類別中的成員,那麼重新命名其中一個成員。
class A {
void m() {}
}
class B extends A {
void m2() {}
}
避免空的_else
#空的陳述式在 'else' 子句中是不允許的。
描述
#當 `else` 後面的陳述式是空的陳述式 (分號) 時,分析器會產生此診斷訊息。
如需更多資訊,請參閱 avoid_empty_else
的文件。
範例
#以下程式碼會產生此診斷訊息,因為 `else` 後面的陳述式是空的陳述式
void f(int x, int y) {
if (x > y)
print("1");
else ;
print("2");
}
常見修正方式
#如果空陳述式之後的陳述式旨在僅在條件為 `false` 時執行,那麼移除空陳述式。
void f(int x, int y) {
if (x > y)
print("1");
else
print("2");
}
如果沒有旨在僅在條件為 `false` 時執行的程式碼,那麼移除整個 `else` 子句。
void f(int x, int y) {
if (x > y)
print("1");
print("2");
}
避免在_forEach呼叫中使用函式字面值
#函式字面量不應傳遞給 'forEach'。
描述
#當 `Iterable.forEach` 的引數是閉包時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 `forEach` 調用的引數是一個閉包
void f(Iterable<String> s) {
s.forEach((e) => print(e));
}
常見修正方式
#如果閉包可以被 tear-off 取代,那麼取代閉包。
void f(Iterable<String> s) {
s.forEach(print);
}
如果閉包無法被 tear-off 取代,那麼使用 `for` 迴圈來迭代元素。
void f(Iterable<String> s) {
for (var e in s) {
print(e);
}
}
避免_FutureOr<void>
#不要使用類型 'FutureOr'。
描述
#當類型 FutureOr<void>
用作結果的類型時 (精確地說:它用在非變異位置),分析器會產生此診斷訊息。類型 FutureOr<void>
是有問題的,因為它可能看似編碼結果是 Future<void>
,或者結果應該被捨棄 (當它是 void
時)。然而,沒有安全的方法可以偵測我們是屬於哪種情況,因為類型為 void
的表達式可以評估為任何物件,包括任何類型的 future。
具有類型含義類似於「忽略此物件;另外,請看一下,因為它可能是一個 future」在概念上也是不合理的。
對於類型 `FutureOr<void>` 的逆變情況 (例如,對於形式參數的類型) 進行了例外處理,並且對於這些情況不會發出警告。此例外的原因是該類型不描述結果,而是描述對其他人提供的值的約束。同樣地,對於類型別名宣告也進行了例外處理,因為它們很可能在逆變位置中使用 (例如,作為形式參數的類型)。因此,在類型別名宣告中,僅檢查類型參數邊界。
範例
#import 'dart:async';
FutureOr<void> m() => null;
常見修正方式
#類型 `FutureOr<void>` 的一個替代方案 (通常很有用) 是 `Future<void>?`。此類型編碼結果是 `Future<void>` 或 null,並且在運行時沒有歧義,因為沒有物件可以同時具有這兩種類型。
可能並非總是可以使用類型 `Future<void>?` 作為類型 `FutureOr<void>` 的替代方案,因為後者是所有類型的超類型,而前者不是。在這種情況下,將 `FutureOr<void>` 替換為類型 `void` 可能是一種有用的補救措施。
避免初始化為_null
#多餘地初始化為 'null'。
描述
#當可為 null 的變數被明確初始化為 `null` 時,分析器會產生此診斷訊息。變數可以是區域變數、欄位或頂層變數。
未明確初始化的變數或欄位會自動初始化為 `null`。在 Dart 中沒有「未初始化的記憶體」的概念。
範例
#以下程式碼會產生此診斷訊息,因為變數 `f` 被明確初始化為 `null`
class C {
int? f = null;
void m() {
if (f != null) {
print(f);
}
}
}
常見修正方式
#移除不必要的初始化。
class C {
int? f;
void m() {
if (f != null) {
print(f);
}
}
}
避免_print
#不要在生產程式碼中調用 'print'。
描述
#當在生產程式碼中調用函式 `print` 時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為函式 `print` 無法在生產環境中調用。
void f(int x) {
print('x = $x');
}
常見修正方式
#如果您正在編寫使用 Flutter 的程式碼,那麼請使用函式 debugPrint
,並使用 kDebugMode
進行測試保護。
import 'package:flutter/foundation.dart';
void f(int x) {
if (kDebugMode) {
debugPrint('x = $x');
}
}
如果您正在編寫不使用 Flutter 的程式碼,那麼請使用記錄服務 (例如 package:logging
) 來寫入資訊。
避免相對_lib匯入
#不能使用相對路徑匯入 'lib' 中的程式庫。
描述
#當 `import` 指令中的 URI 在路徑中包含 `lib` 時,分析器會產生此診斷訊息。
範例
#假設 `lib` 目錄中有名為 `a.dart` 的檔案
class A {}
以下程式碼會產生此診斷訊息,因為匯入包含一個包含 `lib` 的路徑
import '../lib/a.dart';
常見修正方式
#重寫匯入以不在 URI 中包含 `lib`。
import 'a.dart';
避免重新命名方法參數
#參數名稱 '{0}' 與覆寫方法中的名稱 '{1}' 不符。
描述
#當從超類別覆寫方法的方法更改參數名稱時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 `B` 中方法 `m` 的參數名為 `b`,這與 `A` 中覆寫方法的參數名稱不同
class A {
void m(int a) {}
}
class B extends A {
@override
void m(int b) {}
}
常見修正方式
#重新命名其中一個參數,使它們相同。
class A {
void m(int a) {}
}
class B extends A {
@override
void m(int a) {}
}
避免_setter的傳回類型
#setter 上不必要的傳回類型。
描述
#當 setter 具有明確的傳回類型時,分析器會產生此診斷訊息。
Setter 永遠不會傳回值,因此宣告 setter 的傳回類型是多餘的。
範例
#以下程式碼會產生此診斷訊息,因為 setter `s` 具有明確的傳回類型 (`void`)
void set s(int p) {}
常見修正方式
#移除傳回類型。
set s(int p) {}
避免為_void傳回_null
#不要從傳回類型為 'void' 的函式傳回 'null'。
不要從傳回類型為 'void' 的方法傳回 'null'。
描述
#當傳回類型為 `void` 的函式明確傳回 `null` 時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為在 `void` 函式中有明確的 `null` 傳回
void f() {
return null;
}
常見修正方式
#移除不必要的明確 `null`。
void f() {
return;
}
避免遮蔽類型參數
#類型參數 '{0}' 遮蔽了封閉 {1} 的類型參數。
描述
#當類型參數遮蔽了封閉宣告的類型參數時,分析器會產生此診斷訊息。
使用不同的類型參數遮蔽類型參數可能會導致難以偵錯的細微錯誤。
範例
#以下程式碼會產生此診斷訊息,因為方法 `m` 定義的類型參數 `T` 遮蔽了類別 `C` 定義的類型參數 `T`
class C<T> {
void m<T>() {}
}
常見修正方式
#重新命名其中一個類型參數。
class C<T> {
void m<S>() {}
}
避免在運算式陳述式中使用單一串聯
#不必要的串聯表達式。
描述
#當使用單一串聯運算子且表達式的值未用於任何用途 (例如賦值給變數或作為引數傳遞) 時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為串聯表達式 `s..length` 的值未被使用
void f(String s) {
s..length;
}
常見修正方式
#將串聯運算子替換為簡單的存取運算子。
void f(String s) {
s.length;
}
避免緩慢的_async_IO
#使用非同步 'dart:io' 方法。
描述
#當使用具有同步等效項的非同步檔案 I/O 方法時,分析器會產生此診斷訊息。
以下是標記的特定非同步方法
Directory.exists
Directory.stat
File.lastModified
File.exists
File.stat
FileSystemEntity.isDirectory
FileSystemEntity.isFile
FileSystemEntity.isLink
FileSystemEntity.type
範例
#以下程式碼會產生此診斷訊息,因為調用了非同步方法 `exists`
import 'dart:io';
Future<void> g(File f) async {
await f.exists();
}
常見修正方式
#使用方法的同步版本。
import 'dart:io';
void g(File f) {
f.existsSync();
}
避免類型轉字串
#在生產程式碼中對 'Type' 使用 'toString' 是不安全的。
描述
#當在靜態類型為 `Type` 的值上調用方法 `toString` 時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為方法 `toString` 在 `runtimeType` 傳回的 `Type` 上調用
bool isC(Object o) => o.runtimeType.toString() == 'C';
class C {}
常見修正方式
#如果類型必須完全相同,那麼使用明確的比較。
bool isC(Object o) => o.runtimeType == C;
class C {}
如果類型的子類型的實例傳回 `true` 是可以接受的,那麼使用類型檢查。
bool isC(Object o) => o is C;
class C {}
避免類型作為參數名稱
#參數名稱 '{0}' 與可見類型名稱相符。
描述
#當參數列表中的參數名稱與可見類型 (名稱在作用域內的類型) 相同時,分析器會產生此診斷訊息。
這通常表示預期的參數名稱遺失,導致使用類型名稱作為參數名稱而不是參數的類型。即使情況並非如此 (參數名稱是有意的),參數名稱也會遮蔽現有類型,這可能會導致難以診斷的錯誤。
範例
#以下程式碼會產生此診斷訊息,因為函式 `f` 有一個名為 `int` 的參數,它遮蔽了 `dart:core` 中的類型 `int`
void f(int) {}
常見修正方式
#如果缺少參數名稱,那麼為參數新增名稱。
void f(int x) {}
如果參數旨在具有 `dynamic` 的隱式類型,那麼重新命名參數,使其不會遮蔽任何可見類型的名稱。
void f(int_) {}
避免不必要的容器
#'Container' 的不必要實例。
描述
#當 widget 樹包含 `Container` 的實例且建構子的唯一引數是 `child:` 時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 `Container` 建構子的調用僅具有 `child:` 引數
import 'package:flutter/material.dart';
Widget buildRow() {
return Container(
child: Row(
children: [
Text('a'),
Text('b'),
],
)
);
}
常見修正方式
#如果您打算為建構子提供其他引數,那麼新增它們。
import 'package:flutter/material.dart';
Widget buildRow() {
return Container(
color: Colors.red.shade100,
child: Row(
children: [
Text('a'),
Text('b'),
],
)
);
}
如果不需要其他引數,那麼解包子 widget。
import 'package:flutter/material.dart';
Widget buildRow() {
return Row(
children: [
Text('a'),
Text('b'),
],
);
}
避免在_Flutter中使用網頁程式庫
#不要在 Flutter web 外掛程式之外使用僅限 web 的程式庫。
描述
#當不是 web 外掛程式的套件中的程式庫包含僅限 web 的程式庫的匯入時,分析器會產生此診斷訊息。
dart:html
dart:js
dart:js_util
dart:js_interop
dart:js_interop_unsafe
package:js
package:web
範例
#當在不是 web 外掛程式的套件中找到時,以下程式碼會產生此診斷訊息,因為它匯入了 `dart:html`
import 'dart:html';
import 'package:flutter/material.dart';
class C {}
常見修正方式
#如果套件不打算成為 web 外掛程式,那麼移除匯入。
import 'package:flutter/material.dart';
class C {}
如果套件打算成為 web 外掛程式,那麼將以下幾行新增到套件的 `pubspec.yaml` 檔案中。
flutter:
plugin:
platforms:
web:
pluginClass: HelloPlugin
fileName: hello_web.dart
如需更多資訊,請參閱 開發套件和外掛程式。
僅等待_Future
#在 '{0}' 的實例上使用 'await',它不是 'Future' 的子類型。
描述
#當 `await` 後面的表達式具有 `Future<T>`、`FutureOr<T>`、`Future<T>?`、`FutureOr<T>?` 或 `dynamic` 以外的任何類型時,分析器會產生此診斷訊息。
對於表達式 `await null` 進行了例外處理,因為它是引入微任務延遲的常用方法。
除非表達式可以產生 `Future`,否則 `await` 是不必要的,並且可能導致讀者假設不存在的非同步級別。
範例
#以下程式碼會產生此診斷訊息,因為 `await` 後面的表達式具有 `int` 類型
void f() async {
await 23;
}
常見修正方式
#移除 `await`。
void f() async {
23;
}
駝峰式命名擴充功能
#擴充功能名稱 '{0}' 不是 UpperCamelCase 識別符。
描述
#當擴充功能的名稱未使用 'UpperCamelCase' 命名慣例時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為擴充功能的名稱不是以大寫字母開頭
extension stringExtension on String {}
常見修正方式
#如果擴充功能需要有名稱 (需要在此外程式庫之外可見),那麼重新命名擴充功能,使其具有有效的名稱。
extension StringExtension on String {}
如果擴充功能不需要有名稱,那麼移除擴充功能的名稱。
extension on String {}
駝峰式命名類型
#類型名稱 '{0}' 不是 UpperCamelCase 識別符。
描述
#當類型 (類別、mixin、列舉或 typedef) 的名稱未使用 'UpperCamelCase' 命名慣例時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為類別的名稱不是以大寫字母開頭
class c {}
常見修正方式
#重新命名類型,使其具有有效的名稱。
class C {}
取消訂閱
#'StreamSubscription' 的未取消實例。
描述
#當建立 `StreamSubscription` 的實例但未調用方法 `cancel` 時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 `subscription` 未被取消
import 'dart:async';
void f(Stream stream) {
// ignore: unused_local_variable
var subscription = stream.listen((_) {});
}
常見修正方式
#取消 subscription。
import 'dart:async';
void f(Stream stream) {
var subscription = stream.listen((_) {});
subscription.cancel();
}
關閉接收器
#'Sink' 的未關閉實例。
描述
#當建立 `Sink` 的實例但未調用方法 `close` 時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 `sink` 未被關閉
import 'dart:io';
void g(File f) {
var sink = f.openWrite();
sink.write('x');
}
常見修正方式
#關閉 sink。
import 'dart:io';
void g(File f) {
var sink = f.openWrite();
sink.write('x');
sink.close();
}
集合方法不相關的類型
#引數類型 '{0}' 與 '{1}' 無關。
描述
#當核心程式庫中的任何方法以不適當類型的引數調用時,分析器會產生此診斷訊息。這些方法是不為參數提供足夠特定類型的方法,以允許常規類型檢查捕獲錯誤。
檢查的引數是
Iterable<E>.contains
的引數應與E
相關List<E>.remove
的引數應與E
相關Map<K, V>.containsKey
的引數應與K
相關Map<K, V>.containsValue
的引數應與V
相關Map<K, V>.remove
的引數應與K
相關Map<K, V>.[]
的引數應與K
相關Queue<E>.remove
的引數應與E
相關Set<E>.lookup
的引數應與E
相關Set<E>.remove
的引數應與E
相關
範例
#以下程式碼會產生此診斷訊息,因為 `contains` 的引數是一個 `String`,它無法賦值給 `int`,列表 `l` 的元素類型
bool f(List<int> l) => l.contains('1');
常見修正方式
#如果元素類型是正確的,那麼更改引數以具有相同的類型。
bool f(List<int> l) => l.contains(1);
如果引數類型是正確的,那麼更改元素類型。
bool f(List<String> l) => l.contains('1');
常數識別項名稱
#常數名稱 '{0}' 不是 lowerCamelCase 識別符。
描述
#當常數的名稱不遵循 lowerCamelCase 命名慣例時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為頂層變數的名稱不是 lowerCamelCase 識別符
const EMPTY_STRING = '';
常見修正方式
#重寫名稱以遵循 lowerCamelCase 命名慣例。
const emptyString = '';
finally中的控制流程
#在 'finally' 子句中使用 '{0}'。
描述
#當 `finally` 子句包含 `return`、`break` 或 `continue` 陳述式時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為在 `finally` 區塊內有一個 `return` 陳述式
int f() {
try {
return 1;
} catch (e) {
print(e);
} finally {
return 0;
}
}
常見修正方式
#如果不需要該陳述式,那麼移除該陳述式,如果區塊為空,則移除 `finally` 子句。
int f() {
try {
return 1;
} catch (e) {
print(e);
}
}
如果需要該陳述式,那麼將該陳述式移動到 `finally` 區塊之外。
int f() {
try {
return 1;
} catch (e) {
print(e);
}
return 0;
}
流程控制結構中的大括號
#{0} 中的陳述式應該用區塊括起來。
描述
#當控制結構 (`if`、`for`、`while` 或 `do` 陳述式) 具有區塊以外的陳述式時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 `then` 陳述式未用區塊括起來
int f(bool b) {
if (b)
return 1;
return 0;
}
常見修正方式
#在應該是區塊的陳述式周圍新增大括號。
int f(bool b) {
if (b) {
return 1;
}
return 0;
}
懸掛的程式庫文件註解
#懸空的程式庫文件註解。
描述
#當看似是程式庫文件的文件註解後面沒有 `library` 指令時,分析器會產生此診斷訊息。更具體地說,當文件註解出現在程式庫中的第一個指令之前 (假設它不是 `library` 指令),或在第一個頂層宣告之前,並且與該宣告之間隔著一個或多個空行時,就會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為在第一個 `import` 指令之前有一個文件註解
/// This is a great library.
import 'dart:core';
以下程式碼會產生此診斷訊息,因為在第一個類別宣告之前有一個文件註解,但註解和宣告之間有一個空行。
/// This is a great library.
class C {}
常見修正方式
#如果註解是程式庫文件,那麼新增一個沒有名稱的 `library` 指令。
/// This is a great library.
library;
import 'dart:core';
如果註解是以下宣告的文件,那麼移除空行。
/// This is a great library.
class C {}
依賴參考的套件
#匯入的套件 '{0}' 不是匯入套件的依賴項。
描述
#當套件匯入參照到未在 pubspec.yaml
檔案中指定的套件時,分析器會產生此診斷訊息。
明確地依賴您參考的套件可確保它們始終存在,並允許您對它們設定依賴項約束,以防止重大變更。
範例
#給定一個包含以下內容的 pubspec.yaml
檔案
dependencies:
meta: ^3.0.0
以下程式碼會產生此診斷訊息,因為沒有對套件 a
的依賴項
import 'package:a/a.dart';
常見修正方式
#依賴項應該是常規依賴項還是開發依賴項,取決於套件是從公共函式庫(lib
或 bin
下的函式庫)還是僅從私有函式庫(例如 test
下的函式庫)引用。
如果套件至少從一個公共函式庫引用,則在 pubspec.yaml
檔案的 dependencies
欄位下新增對該套件的常規依賴項
dependencies:
a: ^1.0.0
meta: ^3.0.0
如果套件僅從私有函式庫引用,則在 pubspec.yaml
檔案的 dev_dependencies
欄位下新增對該套件的開發依賴項
dependencies:
meta: ^3.0.0
dev_dependencies:
a: ^1.0.0
空的_catch區塊
#空的 catch 區塊。
描述
#當 catch
子句中的區塊為空時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 catch 區塊為空
void f() {
try {
print('Hello');
} catch (exception) {}
}
常見修正方式
#如果例外狀況不應被忽略,則新增程式碼來處理例外狀況
void f() {
try {
print('We can print.');
} catch (exception) {
print("We can't print.");
}
}
如果例外狀況旨在被忽略,則新增註解說明原因
void f() {
try {
print('We can print.');
} catch (exception) {
// Nothing to do.
}
}
如果例外狀況旨在被忽略,並且沒有充分的理由解釋原因,則重新命名例外狀況參數
void f() {
try {
print('We can print.');
} catch (_) {}
}
空的建構子主體
#空的建構子主體應使用 ';' 而不是 '{}' 撰寫。
描述
#當建構子具有空的區塊主體時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 C
的建構子具有空的區塊主體
class C {
C() {}
}
常見修正方式
#將區塊替換為分號
class C {
C();
}
空的陳述式
#不必要的空陳述式。
描述
#當找到空陳述式時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為由 while
迴圈控制的陳述式是空陳述式
void f(bool condition) {
while (condition);
g();
}
void g() {}
常見修正方式
#如果沒有需要控制的陳述式,則移除空陳述式及其所屬的控制結構(請注意,移除的任何其他程式碼是否具有需要保留的副作用)
void f(bool condition) {
g();
}
void g() {}
如果沒有需要控制的陳述式,但由於其他原因仍然需要控制結構,則將空陳述式替換為區塊,以使程式碼的結構更清晰
void f(bool condition) {
while (condition) {}
g();
}
void g() {}
如果有需要控制的陳述式,則移除空陳述式並調整程式碼,使適當的陳述式受到控制,可能需要新增區塊
void f(bool condition) {
while (condition) {
g();
}
}
void g() {}
檔案名稱
#檔案名稱 '{0}' 不是 lower_case_with_underscores 識別符。
描述
#當 .dart
檔案的名稱未使用 lower_case_with_underscores 時,分析器會產生此診斷訊息。
範例
#名為 SliderMenu.dart
的檔案會產生此診斷訊息,因為檔案名稱使用了 UpperCamelCase 慣例。
常見修正方式
#重新命名檔案以使用 lower_case_with_underscores 慣例,例如 slider_menu.dart
。
hash和_equals
#缺少 '{0}' 的對應覆寫。
描述
#當類別或 mixin 覆寫了 ==
的定義但未覆寫 hashCode
的定義,反之亦然,覆寫了 hashCode
的定義但未覆寫 ==
的定義時,分析器會產生此診斷訊息。
對於常見的雜湊表實作能夠正常運作,物件的 ==
運算子和 hashCode
屬性都必須保持一致。因此,當覆寫任一方法時,兩者都應被覆寫。
範例
#以下程式碼會產生此診斷訊息,因為類別 C
覆寫了 ==
運算子,但未覆寫 getter hashCode
class C {
final int value;
C(this.value);
@override
bool operator ==(Object other) =>
other is C &&
other.runtimeType == runtimeType &&
other.value == value;
}
常見修正方式
#如果您需要覆寫其中一個成員,則新增另一個成員的覆寫
class C {
final int value;
C(this.value);
@override
bool operator ==(Object other) =>
other is C &&
other.runtimeType == runtimeType &&
other.value == value;
@override
int get hashCode => value.hashCode;
}
如果您不需要覆寫任何一個成員,則移除不必要的覆寫
class C {
final int value;
C(this.value);
}
實作匯入
#從另一個套件的 'lib/src' 目錄匯入函式庫。
描述
#當匯入參照到不同套件的 lib/src
目錄內的函式庫時,分析器會產生此診斷訊息,這違反了 pub 套件的慣例。
範例
#以下程式碼,假設它不是 ffi
套件的一部分,會產生此診斷訊息,因為被匯入的函式庫位於頂層 src
目錄內
import 'package:ffi/src/allocation.dart';
常見修正方式
#如果被匯入的函式庫包含屬於公共 API 的程式碼,則匯入匯出公共 API 的公共函式庫
import 'package:ffi/ffi.dart';
如果被匯入的函式庫不是套件公共 API 的一部分,則尋找其他方法來達成您的目標(假設可能),或開啟 issue 要求套件作者將其納入公共 API。
隱含呼叫拆解
#方法 'call' 的隱式 tear-off。
描述
#當具有 call
方法的物件被賦值給函式類型變數時,分析器會產生此診斷訊息,隱式地 tear off call
方法。
範例
#以下程式碼會產生此診斷訊息,因為 Callable
的實例被傳遞給期望 Function
的函式
class Callable {
void call() {}
}
void callIt(void Function() f) {
f();
}
void f() {
callIt(Callable());
}
常見修正方式
#顯式地 tear off call
方法
class Callable {
void call() {}
}
void callIt(void Function() f) {
f();
}
void f() {
callIt(Callable().call);
}
使用_JS互通類型進行無效的執行階段檢查
#從 '{0}' 到 '{1}' 的轉換會將 Dart 值轉換為 JS 互通類型,這可能不具有跨平台一致性。
從 '{0}' 到 '{1}' 的轉換會將 JS 互通值轉換為 Dart 類型,這可能不具有跨平台一致性。
從 '{0}' 到 '{1}' 的轉換會將 JS 互通值轉換為不相容的 JS 互通類型,這可能不具有跨平台一致性。
'{0}' 和 '{1}' 之間的執行階段檢查會檢查 Dart 值是否為 JS 互通類型,這可能不具有跨平台一致性。
'{0}' 和 '{1}' 之間的執行階段檢查會檢查 JS 互通值是否為 Dart 類型,這可能不具有跨平台一致性。
'{0}' 和 '{1}' 之間的執行階段檢查涉及兩個 JS 互通類型之間可能不具有跨平台一致性的非簡單執行階段檢查。
'{0}' 和 '{1}' 之間的執行階段檢查涉及 JS 互通值和不相關的 JS 互通類型之間的執行階段檢查,這將始終為 true,並且不會檢查底層類型。
描述
#當 is
測試具有以下情況時,分析器會產生此診斷訊息:
- 右手邊是 JS 互通類型,無論是直接的還是作為另一個類型的類型參數,或
- 左手邊是 JS 互通值。
範例
#以下程式碼會產生此診斷訊息,因為 JS 互通類型 JSBoolean
在 is
測試的右手邊
import 'dart:js_interop';
bool f(Object b) => b is JSBoolean;
以下程式碼會產生此診斷訊息,因為 JS 互通類型 JSString
用作 is
測試右手邊的類型參數
import 'dart:js_interop';
bool f(List<Object> l) => l is List<JSString>;
以下程式碼會產生此診斷訊息,因為 JS 互通值 a
在 is
測試的左手邊
import 'dart:js_interop';
bool f(JSAny a) => a is String;
常見修正方式
#使用 JS 互通輔助程式,例如 isA
,來檢查 JS 互通值的底層類型
import 'dart:js_interop';
void f(Object b) => b.jsify()?.isA<JSBoolean>();
無效地使用請勿提交的成員
#'{0}' 的使用不應提交到原始碼控制。
描述
#當使用 @doNotSubmit
註解的成員在也使用 @doNotSubmit
註解的成員宣告之外被參照時,分析器會產生此診斷訊息。
範例
#假設一個檔案 a.dart
包含以下宣告
import 'package:meta/meta.dart';
@doNotSubmit
void emulateCrash() { /* ... */ }
以下程式碼會產生此診斷訊息,因為宣告在也使用 @doNotSubmit
註解的成員之外被參照
import 'a.dart';
void f() {
emulateCrash();
}
常見修正方式
#最常見的情況是,在完成本機測試後,應移除對成員的參照。
如果在成員之上建構額外功能,也請使用 @doNotSubmit
註解新新增的成員
import 'package:meta/meta.dart';
import 'a.dart';
@doNotSubmit
void emulateCrashWithOtherFunctionality() {
emulateCrash();
// do other things.
}
程式庫註解
#此註解應附加到函式庫指令。
描述
#當適用於整個函式庫的註解未與 library
指令關聯時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 TestOn
註解(適用於整個函式庫)與 import
指令而不是 library
指令關聯
@TestOn('browser')
import 'package:test/test.dart';
void main() {}
常見修正方式
#將註解與 library
指令關聯,必要時新增一個
@TestOn('browser')
library;
import 'package:test/test.dart';
void main() {}
程式庫名稱
#函式庫名稱 '{0}' 不是 lower_case_with_underscores 識別符。
描述
#當函式庫的名稱未使用 lower_case_with_underscores 命名慣例時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為函式庫名稱 libraryName
不是 lower_case_with_underscores 識別符
library libraryName;
常見修正方式
#如果不需要函式庫名稱,則移除函式庫名稱
library;
如果需要函式庫名稱,則將其轉換為使用 lower_case_with_underscores 命名慣例
library library_name;
程式庫前置詞
#前綴 '{0}' 不是 lower_case_with_underscores 識別符。
描述
#當匯入前綴未使用 lower_case_with_underscores 命名慣例時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為前綴 ffiSupport
不是 lower_case_with_underscores 識別符
import 'package:ffi/ffi.dart' as ffiSupport;
常見修正方式
#轉換前綴以使用 lower_case_with_underscores 命名慣例
import 'package:ffi/ffi.dart' as ffi_support;
公用_API中的程式庫私有類型
#在公共 API 中無效地使用私有類型。
描述
#當函式庫公共 API 中參照了不屬於該函式庫公共 API 的類型時,分析器會產生此診斷訊息。
在公共 API 中使用私有類型可能會使 API 在定義函式庫之外無法使用。
範例
#以下程式碼會產生此診斷訊息,因為公共函式 f
的參數 c
具有函式庫私有類型 (_C
)
void f(_C c) {}
class _C {}
常見修正方式
#如果 API 不需要於定義函式庫之外使用,則將其設為私有
void _f(_C c) {}
class _C {}
如果 API 需要成為函式庫公共 API 的一部分,則使用不同的公共類型,或將被參照的類型設為公共
void f(C c) {}
class C {}
僅限字面值的布林運算式
#布林運算式具有常數值。
描述
#當 if
或迴圈陳述式中條件的值已知始終為 true
或始終為 false
時,分析器會產生此診斷訊息。 while
迴圈的條件為布林文字 true
時除外。
範例
#以下程式碼會產生此診斷訊息,因為條件將始終評估為 true
void f() {
if (true) {
print('true');
}
}
lint 將評估由常數組成的運算式子集,因此以下程式碼也會產生此診斷訊息,因為條件將始終評估為 false
void g(int i) {
if (1 == 0 || 3 > 4) {
print('false');
}
}
常見修正方式
#如果條件錯誤,則更正條件,使其值在編譯時無法得知
void g(int i) {
if (i == 0 || i > 4) {
print('false');
}
}
如果條件正確,則簡化程式碼以不評估條件
void f() {
print('true');
}
清單中沒有相鄰字串
#請勿在列表文字中使用相鄰的字串。
描述
#當兩個字串文字在列表文字中相鄰時,分析器會產生此診斷訊息。 Dart 中相鄰的字串會串連在一起形成單個字串,但意圖可能是每個字串都是列表中的單獨元素。
範例
#以下程式碼會產生此診斷訊息,因為字串 'a'
和 'b'
相鄰
List<String> list = ['a' 'b', 'c'];
常見修正方式
#如果兩個字串旨在成為列表的單獨元素,則在它們之間新增逗號
List<String> list = ['a', 'b', 'c'];
如果兩個字串旨在成為單個串連的字串,則手動合併字串
List<String> list = ['ab', 'c'];
或使用 +
運算子來串連字串
List<String> list = ['a' + 'b', 'c'];
沒有重複的_case值
#case 子句的值 ('{0}') 等於較早的 case 子句的值 ('{1}')。
描述
#當同一個 switch
陳述式中的兩個或多個 case
子句具有相同的值時,分析器會產生此診斷訊息。
第一個之後的任何 case
子句都無法執行,因此具有重複的 case
子句會產生誤導。
此診斷訊息通常是由於錯字或常數值的變更所導致。
範例
#以下程式碼會產生此診斷訊息,因為兩個 case 子句具有相同的值 (1)
// @dart = 2.14
void f(int v) {
switch (v) {
case 1:
break;
case 1:
break;
}
}
常見修正方式
#如果其中一個子句應具有不同的值,則變更子句的值
void f(int v) {
switch (v) {
case 1:
break;
case 2:
break;
}
}
如果值正確,則將陳述式合併到單個子句中
void f(int v) {
switch (v) {
case 1:
break;
}
}
程式庫前置詞沒有前導底線
#函式庫前綴 '{0}' 以底線開頭。
描述
#當在匯入上宣告的前綴名稱以底線開頭時,分析器會產生此診斷訊息。
函式庫前綴本質上在宣告函式庫之外不可見,因此指示私有的前導底線沒有增加任何價值。
範例
#以下程式碼會產生此診斷訊息,因為前綴 _core
以底線開頭
import 'dart:core' as _core;
常見修正方式
#移除底線
import 'dart:core' as core;
本機識別項沒有前導底線
#區域變數 '{0}' 以底線開頭。
描述
#當區域變數的名稱以底線開頭時,分析器會產生此診斷訊息。
區域變數本質上在宣告函式庫之外不可見,因此指示私有的前導底線沒有增加任何價值。
範例
#以下程式碼會產生此診斷訊息,因為參數 _s
以底線開頭
int f(String _s) => _s.length;
常見修正方式
#移除底線
int f(String s) => s.length;
createState中沒有邏輯
#請勿在 'createState' 中放置任何邏輯。
描述
#當 StatefulWidget
子類別中的 createState
實作包含除傳回調用零參數建構子的結果之外的任何邏輯時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為建構子調用具有參數
import 'package:flutter/material.dart';
class MyWidget extends StatefulWidget {
@override
MyState createState() => MyState(0);
}
class MyState extends State {
int x;
MyState(this.x);
}
常見修正方式
#重寫程式碼,使 createState
不包含任何邏輯
import 'package:flutter/material.dart';
class MyWidget extends StatefulWidget {
@override
MyState createState() => MyState();
}
class MyState extends State {
int x = 0;
MyState();
}
沒有萬用字元變數使用
#被參照的識別符是萬用字元。
描述
#當參照名稱僅由底線組成的參數或區域變數時,分析器會產生此診斷訊息。 此類名稱在未來版本的 Dart 語言中將變為非綁定,從而使參照變為非法。
範例
#以下程式碼會產生此診斷訊息,因為參數的名稱由兩個底線組成
// @dart = 3.6
void f(int __) {
print(__);
}
以下程式碼會產生此診斷訊息,因為區域變數的名稱由單個底線組成
// @dart = 3.6
void f() {
int _ = 0;
print(_);
}
常見修正方式
#如果變數或參數旨在被參照,則給它一個至少有一個非底線字元的名稱
void f(int p) {
print(p);
}
如果變數或參數不旨在被參照,則將參照替換為不同的運算式
void f() {
print(0);
}
非常數識別項名稱
#變數名稱 '{0}' 不是 lowerCamelCase 識別符。
描述
#當類別成員、頂層宣告、變數、參數、具名參數或未宣告為 const
的具名建構子的名稱未使用 lowerCamelCase 慣例時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為頂層變數 Count
不是以小寫字母開頭
var Count = 0;
常見修正方式
#變更宣告中的名稱以遵循 lowerCamelCase 慣例
var count = 0;
可為 Null 類型參數的空值檢查
#空值檢查運算子不應在類型為可能為可空類型參數的變數上使用。
描述
#當在類型為 T?
的變數上使用空值檢查運算子時,分析器會產生此診斷訊息,其中 T
是允許類型引數為可空的類型參數(沒有邊界或具有可空邊界)。
給定一個具有可空邊界的泛型類型參數 T
,當使用 T?
類型的變數時,很容易引入錯誤的空值檢查。 具體來說,常見的情況是 T? x;
並希望斷言 x
已設定為類型 T
的有效值。 一個常見的錯誤是使用 x!
這樣做。 這幾乎總是錯誤的,因為如果 T
是可空類型,則 x
可能合法地將 null
作為類型 T
的值。
範例
#以下程式碼會產生此診斷訊息,因為 t
的類型為 T?
,並且 T
允許類型引數為可空(因為它沒有 extends
子句)
T f<T>(T? t) => t!;
常見修正方式
#使用類型參數來轉換變數
T f<T>(T? t) => t as T;
覆寫的欄位
#欄位覆寫從 '{0}' 繼承的欄位。
描述
#當類別定義一個欄位,該欄位覆寫了來自超類別的欄位時,分析器會產生此診斷訊息。
用另一個欄位覆寫欄位會導致物件具有兩個不同的欄位,但由於這些欄位具有相同的名稱,因此在給定範圍內只能參照其中一個欄位。 這可能會導致混淆,即對其中一個欄位的參照可能會被誤認為是對另一個欄位的參照。
範例
#以下程式碼會產生此診斷訊息,因為 B
中的欄位 f
遮蔽了 A
中的欄位 f
class A {
int f = 1;
}
class B extends A {
@override
int f = 2;
}
常見修正方式
#如果兩個欄位表示相同的屬性,則從子類別中移除該欄位
class A {
int f = 1;
}
class B extends A {}
如果兩個欄位應該是不同的,則重新命名其中一個欄位
class A {
int f = 1;
}
class B extends A {
int g = 2;
}
如果兩個欄位在某種程度上相關,但不能相同,則尋找不同的方法來實作您需要的語意。
套件名稱
#套件名稱 '{0}' 不是 lower_case_with_underscores 識別符。
描述
#當套件的名稱未使用 lower_case_with_underscores 命名慣例時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為套件的名稱使用了 lowerCamelCase 命名慣例
name: somePackage
常見修正方式
#使用 lower_case_with_underscores 命名慣例重寫套件的名稱
name: some_package
套件前置詞程式庫名稱
#函式庫名稱不是以套件名稱為前綴的點分隔路徑。
描述
#當函式庫的名稱不遵循這些指南時,分析器會產生此診斷訊息
- 所有函式庫名稱都以套件名稱為前綴。
- 使入口函式庫具有與套件相同的名稱。
- 對於套件中的所有其他函式庫,在套件名稱後新增函式庫 Dart 檔案的點分隔路徑。
- 對於
lib
下的函式庫,省略頂層目錄名稱。
例如,給定一個名為 my_package
的套件,以下是套件中各種檔案的函式庫名稱
範例
#假設包含以下程式碼的檔案不在名為 special.dart
的檔案中,而該檔案位於名為 something
的套件的 lib
目錄中(這將是規則的例外),分析器會產生此診斷訊息,因為函式庫的名稱不符合上述指南
library something.special;
常見修正方式
#變更函式庫的名稱以符合指南。
偏好相鄰字串串連
#字串文字不應通過 '+' 運算子串連。
描述
#當使用 +
運算子串連兩個字串文字時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為兩個字串文字正在使用 +
運算子串連
var s = 'a' + 'b';
常見修正方式
#移除運算子
var s = 'a' 'b';
偏好集合字面值
#不必要的建構子調用。
描述
#當使用建構子建立列表、映射或集合,但文字會產生相同的結果時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 Map
的建構子正在被用來建立可以使用文字建立的映射
var m = Map<String, String>();
常見修正方式
#使用文字表示法
var m = <String, String>{};
偏好條件賦值
#'if' 陳述式可以替換為空值感知賦值。
描述
#當變數的賦值取決於變數是否具有值 null
,並且可以使用 ??=
運算子時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為參數 s
正在與 null
進行比較,以確定是否賦值不同的值
int f(String? s) {
if (s == null) {
s = '';
}
return s.length;
}
常見修正方式
#使用 ??=
運算子而不是顯式的 if
陳述式
int f(String? s) {
s ??= '';
return s.length;
}
偏好_const_建構子
#將 'const' 與建構子一起使用以提高效能。
描述
#當 const 建構子的調用既沒有以 const
為前綴,也沒有在 常數上下文 中時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 const
建構子的調用既沒有以 const
為前綴,也沒有在 常數上下文 中
class C {
const C();
}
C c = C();
常見修正方式
#如果上下文可以設為 常數上下文,則執行此操作
class C {
const C();
}
const C c = C();
如果上下文無法設為 常數上下文,則在建構子調用之前新增 const
class C {
const C();
}
C c = const C();
偏好不可變物件中的_const_建構子
#'@immutable' 類別中的建構子應宣告為 'const'。
描述
#當在具有 @immutable
註解的類別中找到非 const
建構子時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 C
中的建構子未宣告為 const
,即使 C
具有 @immutable
註解
import 'package:meta/meta.dart';
@immutable
class C {
final f;
C(this.f);
}
常見修正方式
#如果類別確實旨在是不可變的,則將 const
修飾符新增到建構子
import 'package:meta/meta.dart';
@immutable
class C {
final f;
const C(this.f);
}
如果類別是可變的,則移除 @immutable
註解
class C {
final f;
C(this.f);
}
偏好_const_宣告
#將 'const' 用於初始化為常數值的 final 變數。
描述
#當頂層變數、靜態欄位或區域變數被標記為 final
並且初始化為常數值時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為頂層變數 v
既是 final
又初始化為常數值
final v = const <int>[];
以下程式碼會產生此診斷訊息,因為靜態欄位 f
既是 final
又初始化為常數值
class C {
static final f = const <int>[];
}
以下程式碼會產生此診斷訊息,因為區域變數 v
既是 final
又初始化為常數值
void f() {
final v = const <int>[];
print(v);
}
常見修正方式
#將關鍵字 final
替換為 const
,並從初始化器中移除 const
class C {
static const f = <int>[];
}
偏好_const_字面值以建立不可變物件
#將 'const' 文字用作 '@immutable' 類別的建構子的引數。
描述
#當非 const 列表、映射或集合文字作為引數傳遞給在使用 @immutable
註解的類別中宣告的建構子時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為列表文字 ([1]
) 正在傳遞給不可變類別中的建構子,但不是常數列表
import 'package:meta/meta.dart';
@immutable
class C {
final f;
const C(this.f);
}
C c = C([1]);
常見修正方式
#如果上下文可以設為 常數上下文,則執行此操作
import 'package:meta/meta.dart';
@immutable
class C {
final f;
const C(this.f);
}
const C c = C([1]);
如果上下文無法設為 常數上下文,但可以使用 const
調用建構子,則在建構子調用之前新增 const
import 'package:meta/meta.dart';
@immutable
class C {
final f;
const C(this.f);
}
C c = const C([1]);
如果上下文無法設為 常數上下文,並且無法使用 const
調用建構子,則在集合文字之前新增關鍵字 const
import 'package:meta/meta.dart';
@immutable
class C {
final f;
const C(this.f);
}
C c = C(const [1]);
偏好_contains
#始終為 'false',因為 'indexOf' 始終大於或等於 -1。
始終為 'true',因為 'indexOf' 始終大於或等於 -1。
不必要地使用 'indexOf' 測試是否包含。
描述
#當使用方法 indexOf
,並且結果僅與 -1
或 0
進行比較時,分析器會產生此診斷訊息,其中語意等同於使用 contains
。
範例
#以下程式碼會產生此診斷訊息,因為 if
陳述式中的條件正在檢查列表是否包含字串
void f(List<String> l, String s) {
if (l.indexOf(s) < 0) {
// ...
}
}
常見修正方式
#改用 contains
,必要時取反條件
void f(List<String> l, String s) {
if (l.contains(s)) {
// ...
}
}
偏好雙引號
#不必要地使用單引號。
描述
#當字串文字使用單引號 ('
) 但可以使用雙引號 ("
) 而無需額外跳脫字元且不損害可讀性時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為字串文字使用了單引號,但不需要
void f(String name) {
print('Hello $name');
}
常見修正方式
#使用雙引號代替單引號
void f(String name) {
print("Hello $name");
}
偏好_final_欄位
#私有欄位 {0} 可以是 'final'。
描述
#當私有欄位僅被賦值一次時,分析器會產生此診斷訊息。 欄位可以在多個建構子中初始化,但仍然會被標記,因為這些建構子中只有一個可以運行。
範例
#以下程式碼會產生此診斷訊息,因為欄位 _f
僅被賦值一次,在欄位的初始化器中
class C {
int _f = 1;
int get f => _f;
}
常見修正方式
#將欄位標記為 final
class C {
final int _f = 1;
int get f => _f;
}
偏好使用_for元素而不是_mapFromIterable
#從可迭代物件建構映射時,使用 'for' 元素。
描述
#當 Map.fromIterable
用於建構可以使用 for
元素建構的映射時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 fromIterable
正在被用來建構可以使用 for
元素建構的映射
void f(Iterable<String> data) {
Map<String, int>.fromIterable(
data,
key: (element) => element,
value: (element) => element.length,
);
}
常見修正方式
#使用 for
元素來建構映射
void f(Iterable<String> data) {
<String, int>{
for (var element in data)
element: element.length
};
}
偏好函式宣告而不是變數
#使用函式宣告而不是變數賦值將函式綁定到名稱。
描述
#當閉包被賦值給區域變數,並且該區域變數在任何地方都沒有被重新賦值時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為區域變數 f
被初始化為閉包,並且未被賦值任何其他值
void g() {
var f = (int i) => i * 2;
f(1);
}
常見修正方式
#將區域變數替換為區域函式
void g() {
int f(int i) => i * 2;
f(1);
}
偏好泛型函式類型別名
#在 'typedef' 中使用泛型函式類型語法。
描述
#當 typedef 使用較舊的函式類型別名語法撰寫時,分析器會產生此診斷訊息,在該語法中,被宣告的名稱嵌入在函式類型中。
範例
#以下程式碼會產生此診斷訊息,因為它使用了較舊的語法
typedef void F<T>();
常見修正方式
#重寫 typedef 以使用較新的語法
typedef F<T> = void Function();
偏好_if_null運算子
#當測試 'null' 時,使用 '??' 運算子而不是 '?:'。
描述
#當條件運算式(使用 ?:
運算子)用於在區域變數為 null
時選擇不同的值時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為變數 s
正在與 null
進行比較,以便在 s
為 null
時可以傳回不同的值
String f(String? s) => s == null ? '' : s;
常見修正方式
#改用 if-null 運算子
String f(String? s) => s ?? '';
偏好初始化形式參數
#使用初始化形式參數將參數賦值給欄位。
描述
#當建構子參數用於初始化欄位而不進行修改時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為參數 c
僅用於設定欄位 c
class C {
int c;
C(int c) : this.c = c;
}
常見修正方式
#使用初始化形式參數來初始化欄位
class C {
int c;
C(this.c);
}
偏好內嵌的_add
#新增列表項可以內聯。
新增多個列表項可以內聯。
描述
#當在列表文字上調用方法 add
和 addAll
,並且要新增的元素可以包含在列表文字中時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 add
方法正在被用來新增 b
,但它可以直接包含在列表文字中
List<String> f(String a, String b) {
return [a]..add(b);
}
以下程式碼會產生此診斷訊息,因為 addAll
方法正在被用來新增 b
的元素,但它可以直接包含在列表文字中
List<String> f(String a, List<String> b) {
return [a]..addAll(b);
}
常見修正方式
#如果正在使用 add
方法,則將引數設為列表的元素並移除調用
List<String> f(String a, String b) {
return [a, b];
}
如果正在使用 addAll
方法,則對引數使用擴展運算子以將其元素新增到列表中並移除調用
List<String> f(String a, List<String> b) {
return [a, ...b];
}
偏好內插而不是撰寫字串
#使用插值來組合字串和值。
描述
#當字串文字和計算字串正在使用 +
運算子串連,但字串插值可以達到相同的結果時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為字串 s
使用 +
運算子與其他字串串連
String f(String s) {
return '(' + s + ')';
}
常見修正方式
#使用字串插值
String f(List<String> l) {
return '(${l[0]}, ${l[1]})';
}
偏好_isEmpty
#比較始終為 'false',因為長度始終大於或等於 0。
比較始終為 'true',因為長度始終大於或等於 0。
使用 'isEmpty' 而不是 'length' 來測試集合是否為空。
使用 'isNotEmpty' 而不是 'length' 來測試集合是否為空。
描述
#當調用 Iterable.length
或 Map.length
的結果與零 (0
) 進行相等性比較時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為調用 length
的結果正在檢查是否等於零
int f(Iterable<int> p) => p.length == 0 ? 0 : p.first;
常見修正方式
#將 length
的使用替換為使用 isEmpty
或 isNotEmpty
void f(Iterable<int> p) => p.isEmpty ? 0 : p.first;
偏好_isNotEmpty
#使用 'isNotEmpty' 而不是取反 'isEmpty' 的結果。
描述
#當調用 Iterable.isEmpty
或 Map.isEmpty
的結果被取反時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為調用 Iterable.isEmpty
的結果被取反
void f(Iterable<int> p) => !p.isEmpty ? p.first : 0;
常見修正方式
#重寫程式碼以使用 isNotEmpty
void f(Iterable<int> p) => p.isNotEmpty ? p.first : 0;
偏好_is_not運算子
#使用 'is!' 運算子而不是取反 'is' 運算子的值。
描述
#分析器在前綴 !
運算子被用來否定 is
測試的結果時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為測試 o
是否為 String
的結果,使用了前綴 !
運算子來否定。
String f(Object o) {
if (!(o is String)) {
return o.toString();
}
return o;
}
常見修正方式
#改用 is!
運算子
String f(Object o) {
if (o is! String) {
return o.toString();
}
return o;
}
偏好_Iterable.whereType
#使用 'whereType' 來選取給定類型的元素。
描述
#分析器在方法 Iterable.where
被用來根據元素的類型篩選元素時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為方法 where
被用來僅存取可迭代物件內的字串。
Iterable<Object> f(Iterable<Object> p) => p.where((e) => e is String);
常見修正方式
#重寫程式碼以使用 whereType
Iterable<String> f(Iterable<Object> p) => p.whereType<String>();
這也可能讓您能夠收緊程式碼中的類型,或移除其他類型檢查。
偏好_null_感知運算子
#使用可感知空值運算子 '?.',而不是明確的 'null' 比較。
描述
#分析器在與 null
進行比較以保護成員參考時,以及在受保護的目標為 null
時,null
被用作結果時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為 length
的調用受 null
比較保護,即使預設值為 null
。
int? f(List<int>? p) {
return p == null ? null : p.length;
}
常見修正方式
#改用可感知空值存取運算子
int? f(List<int>? p) {
return p?.length;
}
偏好相對匯入
#對於 'lib' 目錄中的檔案,使用相對匯入。
描述
#分析器在位於 'lib' 目錄內的函式庫中的 import
語句,使用 package:
URI 來參考同一個套件中的另一個函式庫時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為它使用了 package:
URI,但本可以使用相對 URI。
import 'package:my_package/bar.dart';
常見修正方式
#使用相對 URI 來匯入函式庫
import 'bar.dart';
偏好單引號
#不必要地使用雙引號。
描述
#分析器在字串字面值可以使用單引號 ('
) 而不需要額外的跳脫字元,且不會損害可讀性的情況下,卻使用了雙引號 ("
) 時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為字串字面值使用了雙引號,但並不需要。
void f(String name) {
print("Hello $name");
}
常見修正方式
#使用單引號來代替雙引號
void f(String name) {
print('Hello $name');
}
偏好為未初始化的變數輸入類型
#未初始化的欄位應具有明確的類型註解。
未初始化的變數應具有明確的類型註解。
描述
#分析器在沒有初始化器的變數沒有明確的類型註解時,會發出此診斷訊息。
在沒有類型註解或初始化器的情況下,變數的類型為 dynamic
,這允許將任何值賦予變數,通常會導致難以識別的錯誤。
範例
#以下程式碼會發出此診斷訊息,因為變數 r
沒有類型註解或初始化器。
Object f() {
var r;
r = '';
return r;
}
常見修正方式
#如果變數可以被初始化,則添加一個初始化器
Object f() {
var r = '';
return r;
}
如果變數無法被初始化,則添加一個明確的類型註解
Object f() {
String r;
r = '';
return r;
}
偏好_void而不是_null
#不必要地使用類型 'Null'。
描述
#分析器在 Null
被使用在 void
會是有效選擇的位置時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為函數 f
被宣告為返回 null
(在未來某個時間)。
Future<Null> f() async {}
常見修正方式
#將 Null
的使用替換為 void
的使用
Future<void> f() async {}
提供已淘汰訊息
#缺少棄用訊息。
描述
#分析器在使用了 deprecated
註解而不是 Deprecated
註解時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為函數 f
使用了 deprecated
註解。
@deprecated
void f() {}
常見修正方式
#將程式碼轉換為使用較長的形式
@Deprecated('Use g instead. Will be removed in 4.0.0.')
void f() {}
遞迴式_getter
#Getter '{0}' 遞迴地返回自身。
描述
#分析器在 getter 調用自身,導致無限迴圈時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為 getter count
調用自身。
class C {
int _count = 0;
int get count => count;
}
常見修正方式
#更改 getter 使其不調用自身
class C {
int _count = 0;
int get count => _count;
}
安全_pubspec_網址
#不應使用 '{0}' 協定,因為它不安全。
描述
#分析器在 pubspec.yaml
檔案中的 URL 使用非安全協定時,例如 http
,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為 pubspec.yaml
檔案包含一個 http
URL。
dependencies:
example: any
repository: http://github.com/dart-lang/example
常見修正方式
#更改 URL 的協定以使用安全協定,例如 https
dependencies:
example: any
repository: https://github.com/dart-lang/example
用於空白的_尺寸_方塊
#使用 'SizedBox' 將空白添加到佈局中。
描述
#分析器在僅使用 height
和/或 width
參數創建 Container
時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為 Container
僅具有 width
參數。
import 'package:flutter/material.dart';
Widget buildRow() {
return Row(
children: <Widget>[
const Text('...'),
Container(
width: 4,
child: Text('...'),
),
const Expanded(
child: Text('...'),
),
],
);
}
常見修正方式
#將 Container
替換為相同尺寸的 SizedBox
import 'package:flutter/material.dart';
Widget buildRow() {
return Row(
children: <Widget>[
Text('...'),
SizedBox(
width: 4,
child: Text('...'),
),
Expanded(
child: Text('...'),
),
],
);
}
尺寸_方塊_收縮_展開
#使用 'SizedBox.{0}' 以避免需要指定 'height' 和 'width'。
描述
#分析器在 SizedBox
建構子調用同時指定 height
和 width
的值為 0.0
或 double.infinity
時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為 height
和 width
均為 0.0
。
import 'package:flutter/material.dart';
Widget build() {
return SizedBox(
height: 0.0,
width: 0.0,
child: const Text(''),
);
}
以下程式碼會發出此診斷訊息,因為 height
和 width
均為 double.infinity
。
import 'package:flutter/material.dart';
Widget build() {
return SizedBox(
height: double.infinity,
width: double.infinity,
child: const Text(''),
);
}
常見修正方式
#如果兩者都為 0.0
,則使用 SizedBox.shrink
import 'package:flutter/material.dart';
Widget build() {
return SizedBox.shrink(
child: const Text(''),
);
}
如果兩者都為 double.infinity
,則使用 SizedBox.expand
import 'package:flutter/material.dart';
Widget build() {
return SizedBox.expand(
child: const Text(''),
);
}
用於_文件_註解的斜線
#對於文件註解,使用行尾形式 ('///')。
描述
#分析器在文件註解使用區塊註解樣式(以 /**
和 */
分隔)時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為 f
的文件註解使用了區塊註解樣式。
/**
* Example.
*/
void f() {}
常見修正方式
#使用行尾註解樣式
/// Example.
void f() {}
排序_子項_屬性_最後
#'{0}' 參數應為 widget 建構子調用中的最後一個。
描述
#分析器在 child
或 children
參數不是 widget 類別建構子的調用中的最後一個參數時,會發出此診斷訊息。 但如果 child
或 children
參數之後的所有參數都是函數表達式,則會例外。
範例
#以下程式碼會發出此診斷訊息,因為 child
參數不是 Center
建構子調用中的最後一個參數。
import 'package:flutter/material.dart';
Widget createWidget() {
return Center(
child: Text('...'),
widthFactor: 0.5,
);
}
常見修正方式
#將 child
或 children
參數移動到最後
import 'package:flutter/material.dart';
Widget createWidget() {
return Center(
widthFactor: 0.5,
child: Text('...'),
);
}
排序_建構子_優先
#建構子宣告應在非建構子宣告之前。
描述
#分析器在建構子宣告之前有一個或多個非建構子宣告時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為 C
的建構子出現在方法 m
之後。
class C {
void m() {}
C();
}
常見修正方式
#將所有建構子宣告移動到任何其他宣告之前
class C {
C();
void m() {}
}
排序_pub_相依性
#依賴項未按字母順序排序。
描述
#分析器在 pubspec.yaml
檔案中的依賴項映射中的鍵未按字母順序排序時,會發出此診斷訊息。 檢查的依賴項映射為 dependencies
、dev_dependencies
和 dependency_overrides
映射。
範例
#以下程式碼會發出此診斷訊息,因為 dependencies
映射中的條目未排序。
dependencies:
path: any
collection: any
常見修正方式
#排序條目
dependencies:
collection: any
path: any
排序_未命名_建構子_優先
#未命名建構子的位置無效。
描述
#分析器在未命名的建構子出現在命名建構子之後時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為未命名的建構子在命名建構子之後。
class C {
C.named();
C();
}
常見修正方式
#將未命名的建構子移動到任何其他建構子之前
class C {
C();
C.named();
}
等於中的_測試_類型
#在 '==' 中缺少 '{0}' 的類型測試。
描述
#分析器在 ==
運算子的覆寫中,未包含對參數值的類型測試時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為未對 other
進行類型測試。
class C {
final int f;
C(this.f);
@override
bool operator ==(Object other) {
return (other as C).f == f;
}
}
常見修正方式
#執行 is
測試作為計算傳回值的一部分
class C {
final int f;
C(this.f);
@override
bool operator ==(Object other) {
return other is C && other.f == f;
}
}
在_finally中拋出
#在 'finally' 區塊中使用 '{0}'。
描述
#分析器在 finally
區塊內找到 throw
語句時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為在 finally
區塊內有一個 throw
語句。
void f() {
try {
// ...
} catch (e) {
// ...
} finally {
throw 'error';
}
}
常見修正方式
#重寫程式碼,使 throw
語句不在 finally
區塊內
void f() {
try {
// ...
} catch (e) {
// ...
}
throw 'error';
}
類型_初始化_形式
#不要不必要地為初始化形式參數添加類型註解。
描述
#分析器在初始化形式參數 (this.x
) 或 super 參數 (super.x
) 具有與欄位或覆寫參數相同的明確類型註解時,會發出此診斷訊息。
如果建構子參數使用 this.x
來初始化欄位,則參數的類型隱含地與欄位的類型相同。 如果建構子參數使用 super.x
來轉發到 super 建構子,則參數的類型隱含地與 super 建構子參數相同。
範例
#以下程式碼會發出此診斷訊息,因為參數 this.c
具有與欄位 c
相同的明確類型。
class C {
int c;
C(int this.c);
}
以下程式碼會發出此診斷訊息,因為參數 super.a
具有與超類別中的參數 a
相同的明確類型。
class A {
A(int a);
}
class B extends A {
B(int super.a);
}
常見修正方式
#從參數中移除類型註解
class C {
int c;
C(this.c);
}
常數_模式中的類型_字面值
#使用 'TypeName _' 而不是類型字面值。
描述
#分析器在類型字面值作為模式出現時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為類型字面值被用作常數模式。
void f(Object? x) {
if (x case num) {
// ...
}
}
常見修正方式
#如果類型字面值旨在匹配給定類型的物件,則使用變數模式
void f(Object? x) {
if (x case num _) {
// ...
}
}
或物件模式
void f(Object? x) {
if (x case num()) {
// ...
}
}
如果類型字面值旨在匹配類型字面值,則將其寫為常數模式
void f(Object? x) {
if (x case const (num)) {
// ...
}
}
未等待的_Future
#此表達式計算的 'Future' 缺少 'await'。
描述
#分析器在 Future
的實例從 async
(或 async*
)方法或函數內的調用返回,且 future 既未被等待,也未傳遞給 unawaited
函數時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為函數 g
返回 future,但 future 未被等待。
Future<void> f() async {
g();
}
Future<int> g() => Future.value(0);
常見修正方式
#如果 future 需要在後續程式碼執行之前完成,則在調用之前添加 await
Future<void> f() async {
await g();
}
Future<int> g() => Future.value(0);
如果 future 不需要在後續程式碼執行之前完成,則將返回 Future
的調用包裝在 unawaited
函數的調用中
import 'dart:async';
Future<void> f() async {
unawaited(g());
}
Future<int> g() => Future.value(0);
文件_註解中非預期的_HTML
#角括號將被解釋為 HTML。
描述
#分析器在文件註解包含未經允許的例外角括號文本 (<...>
) 時,會發出此診斷訊息。
此類文本被 markdown 解釋為 HTML 標籤,這通常不是預期的。
請參閱 lint 規則描述 以取得允許的例外列表。
範例
#以下程式碼會發出此診斷訊息,因為文件註解包含文本 <int>
,這不是允許的例外之一。
/// Converts a List<int> to a comma-separated String.
String f(List<int> l) => '';
常見修正方式
#如果文本旨在成為程式碼跨度的一部分,則在程式碼周圍添加反引號
/// Converts a `List<int>` to a comma-separated String.
String f(List<int> l) => '';
如果文本旨在成為連結的一部分,則在程式碼周圍添加方括號
/// Converts a [List<int>] to a comma-separated String.
String f(List<int> l) => '';
如果文本旨在按原樣列印,包括角括號,則在角括號之前添加反斜線跳脫字元
/// Converts a List\<int\> to a comma-separated String.
String f(List<int> l) => '';
字串_內插中不必要的_大括號
#字串插值中不必要的花括號。
描述
#分析器在帶有花括號的字串插值被用來插入簡單的識別字,且後續沒有字母數字文本時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為插值元素 ${s}
在不需要時使用了花括號。
String f(String s) {
return '"${s}"';
}
常見修正方式
#移除不必要的花括號
String f(String s) {
return '"$s"';
}
不必要的_const
#不必要的 'const' 關鍵字。
描述
#分析器在 常數上下文 中使用關鍵字 const
時,會發出此診斷訊息。 由於它是隱含的,因此不需要此關鍵字。
範例
#以下程式碼會發出此診斷訊息,因為列表字面值中的關鍵字 const
是不需要的。
const l = const <int>[];
由於變數宣告上的關鍵字 const
,列表是隱含的 const
。
常見修正方式
#移除不必要的關鍵字
const l = <int>[];
不必要的_建構子_名稱
#不必要的 '.new' 建構子名稱。
描述
#分析器在對未命名建構子的參考使用 .new
時,會發出此診斷訊息。 唯一需要 .new
的地方是在建構子拆卸中。
範例
#以下程式碼會發出此診斷訊息,因為 .new
被用來指稱未命名建構子,但在這裡是不需要的。
var o = Object.new();
常見修正方式
#移除不必要的 .new
var o = Object();
不必要的_final
#區域變數不應標記為 'final'。
描述
#分析器在區域變數被標記為 final
時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為區域變數 c
被標記為 final
。
void f(int a, int b) {
final c = a + b;
print(c);
}
常見修正方式
#如果變數沒有類型註解,則將 final
替換為 var
void f(int a, int b) {
var c = a + b;
print(c);
}
如果變數具有類型註解,則移除 final
修飾詞
void f(int a, int b) {
int c = a + b;
print(c);
}
不必要的_getter_和_setter
#不必要地使用 getter 和 setter 來包裝欄位。
描述
#分析器在 getter 和 setter 配對返回並設置欄位的值,而沒有任何額外處理時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為名為 c
的 getter/setter 配對僅公開名為 _c
的欄位。
class C {
int? _c;
int? get c => _c;
set c(int? v) => _c = v;
}
常見修正方式
#將欄位設為 public 並移除 getter 和 setter
class C {
int? c;
}
不必要的_ignore
#診斷訊息 '{0}' 未在此位置產生,因此不需要忽略它。
診斷訊息 '{0}' 未在此檔案中產生,因此不需要忽略它。
描述
#分析器在指定忽略未產生的診斷訊息時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為 unused_local_variable
診斷訊息未在被忽略的位置報告。
// ignore: unused_local_variable
void f() {}
常見修正方式
#移除忽略註解
void f() {}
不必要的_lambda
#閉包應該是拆卸。
描述
#分析器在閉包(lambda)可以被拆卸替換時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為傳遞給 forEach
的閉包僅包含對函數 print
的調用,並使用閉包的參數。
void f(List<String> strings) {
strings.forEach((string) {
print(string);
});
}
常見修正方式
#將閉包替換為正在調用函數或方法的拆卸,並使用閉包
void f(List<String> strings) {
strings.forEach(print);
}
不必要的_late
#不必要的 'late' 修飾詞。
描述
#分析器在具有初始化器的頂層變數或靜態欄位被標記為 late
時,會發出此診斷訊息。 頂層變數和靜態欄位隱含地為 late,因此它們不需要被明確標記。
範例
#以下程式碼會發出此診斷訊息,因為靜態欄位 c
具有修飾詞 late
,即使它具有初始化器。
class C {
static late String c = '';
}
常見修正方式
#移除關鍵字 late
class C {
static String c = '';
}
不必要的_library_名稱
#函式庫名稱不是必要的。
描述
#分析器在 library
指令指定名稱時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為 library
指令包含一個名稱。
library some.name;
class C {}
常見修正方式
#從 library
指令中移除名稱
library;
class C {}
如果函式庫有任何部分,則任何使用函式庫名稱的 part of
宣告都應更新為使用函式庫的 URI。
不必要的_new
#不必要的 'new' 關鍵字。
描述
#分析器在使用關鍵字 new
來調用建構子時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為關鍵字 new
被用來調用來自 Object
的未命名建構子。
var o = new Object();
常見修正方式
#移除關鍵字 new
var o = Object();
不必要的_null_感知_賦值
#不必要地賦值 'null'。
描述
#分析器在可感知空值賦值的右側是 null
字面值時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為可感知空值運算子被用來將 null
賦值給 s
,而 s
已經是 null
。
void f(String? s) {
s ??= null;
}
常見修正方式
#如果應將非 null 值賦值給左側運算元,則更改右側
void f(String? s) {
s ??= '';
}
如果沒有非 null 值賦值給左側運算元,則移除賦值
void f(String? s) {
}
if_null_運算子中不必要的_null
#不必要地使用 '??' 和 'null'。
描述
#分析器在 ??
運算子的右側運算元是字面值 null
時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為 ??
運算子的右側運算元是 null
。
String? f(String? s) => s ?? null;
常見修正方式
#如果應將非 null 值用於右側運算元,則更改右側
String f(String? s) => s ?? '';
如果沒有非 null 值用於右側運算元,則移除運算子和右側運算元
String? f(String? s) => s;
final_變數_宣告不必要的_可為 Null
#類型可以是非可空類型。
描述
#分析器在 final 欄位或變數具有可空類型,但被初始化為非可空值時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為 final 變數 i
具有可空類型 (int?
),但永遠不會是 null
。
final int? i = 1;
常見修正方式
#將類型設為非可空類型
final int i = 1;
不必要的_覆寫
#不必要的覆寫。
描述
#分析器在實例成員覆寫繼承成員,但僅使用完全相同的參數調用覆寫成員時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為方法 D.m
除了調用覆寫方法之外,沒有做任何其他事情。
class C {
int m(int x) => x;
}
class D extends C {
@override
int m(int x) => super.m(x);
}
常見修正方式
#如果該方法應執行比覆寫方法更多的操作,則實作缺失的功能
class C {
int m(int x) => x;
}
class D extends C {
@override
int m(int x) => super.m(x) + 1;
}
如果應通過更改傳回類型或一個或多個參數類型、使其中一個參數為 covariant
、具有文件註解或具有其他註解來修改覆寫方法,則更新程式碼
import 'package:meta/meta.dart';
class C {
int m(int x) => x;
}
class D extends C {
@mustCallSuper
@override
int m(int x) => super.m(x);
}
如果覆寫方法沒有更改或增強程式碼的語義,則移除它
class C {
int m(int x) => x;
}
class D extends C {}
不必要的_括號
#不必要地使用括號。
描述
#分析器在括號的使用不會影響程式碼語義時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為二元表達式周圍的括號是不必要的。
int f(int a, int b) => (a + b);
常見修正方式
#移除不必要的括號
int f(int a, int b) => a + b;
不必要的_原始_字串
#不必要地使用原始字串。
描述
#分析器在字串字面值被標記為原始字串(以 r
作為前綴),但使字串成為原始字串不會更改字串的值時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為字串字面值在沒有 r
的情況下與有 r
的情況下具有相同的值。
var s = r'abc';
常見修正方式
#移除字串字面值前面的 r
var s = 'abc';
不必要的_陳述式
#不必要的語句。
描述
#分析器在表達式語句沒有明顯效果時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為兩個調用傳回值的加法沒有明顯效果。
void f(int Function() first, int Function() second) {
first() + second();
}
常見修正方式
#如果不需要計算表達式,則移除它
void f(int Function() first, int Function() second) {
}
如果需要表達式的值,則使用它,可能首先將其賦值給區域變數
void f(int Function() first, int Function() second) {
print(first() + second());
}
如果需要執行表達式的部分,則移除不必要的部分
void f(int Function() first, int Function() second) {
first();
second();
}
不必要的_字串_跳脫字元
#字串字面值中不必要的跳脫字元。
描述
#分析器在字串中的字元被跳脫,但跳脫它們是不必要時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為單引號不需要在雙引號分隔的字串內被跳脫。
var s = "Don\'t use a backslash here.";
常見修正方式
#移除不必要的反斜線
var s = "Don't use a backslash here.";
不必要的_字串_內插
#不必要地使用字串插值。
描述
#分析器在字串字面值包含單個 String
值變數的插值,且沒有其他字元時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為字串字面值包含單個插值,且不包含插值之外的任何字元。
String f(String s) => '$s';
常見修正方式
#將字串字面值替換為插值的內容
String f(String s) => s;
不必要的_this
#不必要的 'this.' 限定詞。
描述
#分析器在使用關鍵字 this
來存取未被遮蔽的成員時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為使用 this
來存取欄位 _f
是不必要的。
class C {
int _f = 2;
int get f => this._f;
}
常見修正方式
#移除 this.
class C {
int _f = 2;
int get f => _f;
}
展開中不必要的_to_list
#在展開運算符中不必要地使用 'toList'。
描述
#分析器在 toList
被用來將 Iterable
轉換為 List
,緊接著對列表應用展開運算符時,會發出此診斷訊息。 展開運算符可以應用於任何 Iterable
,因此轉換是不必要的。
範例
#以下程式碼會發出此診斷訊息,因為 toList
在 map
的結果上被調用,而 map
的結果是一個 Iterable
,展開運算符可以直接應用於它。
List<String> toLowercase(List<String> strings) {
return [
...strings.map((String s) => s.toLowerCase()).toList(),
];
}
常見修正方式
#移除 toList
的調用
List<String> toLowercase(List<String> strings) {
return [
...strings.map((String s) => s.toLowerCase()),
];
}
不必要的_底線
#不必要地使用多個底線。
描述
#分析器在未使用的變數以多個底線(例如 __
)命名時,會發出此診斷訊息。 可以改用單個 _
萬用字元變數。
範例
#以下程式碼會發出此診斷訊息,因為 __
參數未使用。
void function(int __) { }
常見修正方式
#將名稱替換為單個底線
void function(int _) { }
不相關的_類型_相等性_檢查
#運算元的類型 ('{0}') 不是被匹配的值 ('{1}') 的子類型或超類型。
右側運算元的類型 ('{0}') 不是左側運算元 ('{1}') 的子類型或超類型。
描述
#分析器在比較兩個物件,且兩個物件的靜態類型都不是另一個物件的子類型時,會發出此診斷訊息。
這樣的比較通常會傳回 false
,並且可能無法反映程式設計師的意圖。
可能會有誤報。 例如,名為 Point
的類別可能具有名為 CartesianPoint
和 PolarPoint
的子類別,它們都不是另一個的子類型,但測試實例的相等性可能仍然是適當的。
作為一個具體案例,來自 package:fixnum
的類別 Int64
和 Int32
允許將實例與 int
進行比較,前提是 int
在右側。 此案例已明確地被診斷訊息允許,但其他此類案例則不然。
範例
#以下程式碼會發出此診斷訊息,因為字串 s
正在與整數 1
進行比較。
bool f(String s) {
return s == 1;
}
常見修正方式
#將其中一個運算元替換為與另一個運算元相容的內容
bool f(String s) {
return s.length == 1;
}
不安全的_變異數
#此類型是不安全的:類型參數出現在非協變位置。
描述
#分析器在實例成員具有結果類型,該結果類型在封閉宣告的類型參數中是逆變或不變時,會發出此診斷訊息。 變數的結果類型是其類型,而 getter 或方法的結果類型是其傳回類型。 此 lint 會警告此類成員,因為它們很可能在運行時導致類型檢查失敗,而在調用站點沒有靜態警告或錯誤。
範例
#以下程式碼會發出此診斷訊息,因為 X
作為 f
類型中的參數類型出現,這是此類型參數的逆變發生。
class C<X> {
bool Function(X) f;
C(this.f);
}
這是不安全的:如果 c
具有靜態類型 C<num>
和運行時類型 C<int>
,則 c.f
將會拋出例外。 因此,每個調用 c.f(a)
也會拋出例外,即使在 a
作為 c.f
的參數具有正確類型的情況下也是如此。
常見修正方式
#如果 linted 成員是或可以是私有的,則您可能可以強制執行它永遠不會在除 this
之外的任何其他接收器上存取。 這足以確保不會發生運行時類型錯誤。 例如
class C<X> {
// NB: Ensure manually that `_f` is only accessed on `this`.
// ignore: unsafe_variance
bool Function(X) _f;
C(this._f);
// We can write a forwarding method to allow clients to call `_f`.
bool f(X x) => _f(x);
}
您可以通過為 linted 成員使用更通用的類型來消除不安全的變異數。 在這種情況下,您可能需要在調用站點檢查運行時類型並執行向下轉型。
class C<X> {
bool Function(Never) f;
C(this.f);
}
如果 c
具有靜態類型 C<num>
,則您可以測試類型。 例如,c.f is bool Function(num)
。 如果它具有該類型,您可以安全地使用 num
類型的參數調用它。
您也可以通過使用更通用的類型(如 Function
)來消除不安全的變異數,這本質上是函數的 dynamic
類型。
class C<X> {
Function f;
C(this.f);
}
這將使 c.f(a)
在動態上安全:它將在且僅在參數 a
沒有函數要求的類型時拋出例外。 這比原始版本更好,因為它不會因為靜態類型不匹配而拋出例外。 它只會在為了健全性原因 *必須* 拋出例外時才拋出例外。
同步使用_BuildContext
#不要在非相關的 'mounted' 檢查保護下,跨非同步間隙使用 'BuildContext'。
不要跨非同步間隙使用 'BuildContext'。
描述
#分析器在 StatefulWidget
在非同步間隙之後引用 BuildContext
,且未首先檢查 mounted
屬性時,會發出此診斷訊息。
儲存 BuildContext
以供稍後使用可能會導致難以診斷的崩潰。 非同步間隙隱含地儲存 BuildContext
,使其在診斷時容易被忽略。
範例
#以下程式碼會發出此診斷訊息,因為 context
在 await
之後被傳遞給建構子。
import 'package:flutter/material.dart';
class MyWidget extends Widget {
void onButtonTapped(BuildContext context) async {
await Future.delayed(const Duration(seconds: 1));
Navigator.of(context).pop();
}
}
常見修正方式
#如果可以移除非同步間隙,請執行此操作
import 'package:flutter/material.dart';
class MyWidget extends Widget {
void onButtonTapped(BuildContext context) {
Navigator.of(context).pop();
}
}
如果無法移除非同步間隙,則使用 mounted
來保護 context
的使用
import 'package:flutter/material.dart';
class MyWidget extends Widget {
void onButtonTapped(BuildContext context) async {
await Future.delayed(const Duration(seconds: 1));
if (context.mounted) {
Navigator.of(context).pop();
}
}
}
使用_彩色_方塊
#使用 'ColoredBox' 而不是僅具有 'Color' 的 'Container'。
描述
#分析器在創建僅設置顏色的 Container
時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為設置的容器的唯一屬性是 color
。
import 'package:flutter/material.dart';
Widget build() {
return Container(
color: Colors.red,
child: const Text('hello'),
);
}
常見修正方式
#將 Container
替換為 ColoredBox
import 'package:flutter/material.dart';
Widget build() {
return ColoredBox(
color: Colors.red,
child: const Text('hello'),
);
}
使用_裝飾_方塊
#使用 'DecoratedBox' 而不是僅具有 'Decoration' 的 'Container'。
描述
#分析器在創建僅設置裝飾的 Container
時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為設置的容器的唯一屬性是 decoration
。
import 'package:flutter/material.dart';
Widget buildArea() {
return Container(
decoration: const BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.all(
Radius.circular(5),
),
),
child: const Text('...'),
);
}
常見修正方式
#將 Container
替換為 DecoratedBox
import 'package:flutter/material.dart';
Widget buildArea() {
return DecoratedBox(
decoration: const BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.all(
Radius.circular(5),
),
),
child: const Text('...'),
);
}
Flutter_顏色使用完整的_十六進位_值
#'Color' 的實例應使用 8 位十六進制整數(例如 '0xFFFFFFFF')創建。
描述
#分析器在 Color
類別的建構子的參數是未表示為 8 位十六進制整數的字面值整數時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為參數 (1
) 未表示為 8 位十六進制整數。
import 'package:flutter/material.dart';
Color c = Color(1);
常見修正方式
#將表示形式轉換為 8 位十六進制整數
import 'package:flutter/material.dart';
Color c = Color(0x00000001);
參數使用_函式_類型_語法
#使用泛型函數類型語法來宣告參數 '{0}'。
描述
#分析器在使用較舊樣式的函數值參數語法時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為函數值參數 f
使用了較舊樣式的語法宣告。
void g(bool f(String s)) {}
常見修正方式
#使用泛型函數類型語法來宣告參數
void g(bool Function(String) f) {}
使用_if_null將_null轉換為_布林值
#使用 if-null 運算子將 'null' 轉換為 'bool'。
描述
#分析器在可空 bool
值表達式與布林字面值進行比較(使用 ==
或 !=
)時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為可空布林變數 b
與 true
進行比較。
void f(bool? b) {
if (b == true) {
// Treats `null` as `false`.
}
}
常見修正方式
#重寫條件以改用 ??
void f(bool? b) {
if (b ?? false) {
// Treats `null` as `false`.
}
}
在_widget_建構子中使用_key
#公共 widget 的建構子應具有名為 'key' 的命名參數。
描述
#分析器在不是對其函式庫私有的 Widget
子類別中的建構子,沒有名為 key
的參數時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為類別 MyWidget
的建構子沒有名為 key
的參數。
import 'package:flutter/material.dart';
class MyWidget extends StatelessWidget {
MyWidget({required int height});
}
以下程式碼會發出此診斷訊息,因為類別 MyWidget
的預設建構子沒有名為 key
的參數。
import 'package:flutter/material.dart';
class MyWidget extends StatelessWidget {}
常見修正方式
#將名為 key
的參數添加到建構子,必要時顯式宣告建構子
import 'package:flutter/material.dart';
class MyWidget extends StatelessWidget {
MyWidget({super.key, required int height});
}
私有_欄位和_變數使用_late
#對於具有非可空類型的私有成員,使用 'late'。
描述
#分析器在私有欄位或變數被標記為可空類型,但每個參考都假定變數永遠不是 null
時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為私有頂層變數 _i
是可空的,但每個參考都假定它不會是 null
。
void f() {
_i!.abs();
}
int? _i;
常見修正方式
#將變數或欄位標記為非可空和 late
,以表明它將始終被賦值為非 null 值
void f() {
_i.abs();
}
late int _i;
使用_具名_常數
#使用常數 '{0}' 而不是返回相同物件的建構子。
描述
#分析器在創建的常數具有與已知的 const
變數相同的值時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為有一個已知的 const
欄位 (Duration.zero
) 其值與建構子調用將評估為的值相同。
Duration d = const Duration(seconds: 0);
常見修正方式
#將建構子調用替換為對已知 const
變數的參考
Duration d = Duration.zero;
使用_null_感知_元素
#使用可感知空值標記 '?' 而不是通過 'if' 進行 null 檢查。
描述
#分析器在集合字面值中使用 null 檢查而不是可感知空值標記時,會發出此診斷訊息。
範例
#以下程式碼會發出此診斷訊息,因為使用 null 檢查來決定是否應將 x
插入列表中,而可感知空值標記 '?' 會更簡潔且更簡略。
f(int? x) => [if (x != null) x];
常見修正方式
#將 null 檢查替換為可感知空值標記 '?'
f(int? x) => [?x];
使用_原始_字串
#使用原始字串以避免使用跳脫字元。
描述
#分析器在包含跳脫字元且沒有插值的字串字面值,可以被標記為原始字串以避免需要跳脫字元時,會發出此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為字串包含跳脫字元,如果將字串設為原始字串,則不需要跳脫字元
var s = 'A string with only \\ and \$';
常見修正方式
#將字串標記為原始字串,並移除不必要的反斜線
var s = r'A string with only \ and $';
盡可能使用_rethrow
#使用 'rethrow' 重新擲回捕獲的例外。
描述
#當使用 throw
運算式而非 rethrow
陳述式擲回捕獲的例外時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為捕獲的例外 e
是使用 throw
運算式擲回的
void f() {
try {
// ...
} catch (e) {
throw e;
}
}
常見修正方式
#使用 rethrow
而非 throw
void f() {
try {
// ...
} catch (e) {
rethrow;
}
}
使用_setter來變更_屬性
#此方法用於變更屬性。
描述
#當方法用於設定欄位的值,或函式用於設定最上層變數的值,而沒有其他用途時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為方法 setF
用於設定欄位 _f
的值,且沒有執行其他工作
class C {
int _f = 0;
void setF(int value) => _f = value;
}
常見修正方式
#將方法轉換為 setter
class C {
int _f = 0;
set f(int value) => _f = value;
}
使用_字串_緩衝區
#使用字串緩衝區而非 '+' 來組成字串。
描述
#當在迴圈內將值串連到字串,而未使用 StringBuffer
執行串連時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為字串 result
是在 for
迴圈內透過重複串連計算而得的
String f() {
var result = '';
for (int i = 0; i < 10; i++) {
result += 'a';
}
return result;
}
常見修正方式
#使用 StringBuffer
來計算結果
String f() {
var buffer = StringBuffer();
for (int i = 0; i < 10; i++) {
buffer.write('a');
}
return buffer.toString();
}
在_part_of_指示詞中使用_字串
#part-of 指令使用程式庫名稱。
描述
#當 part of
指令使用程式庫名稱來參照該部分所屬的程式庫時,分析器會產生此診斷訊息。
範例
#假設有名為 lib.dart
的檔案包含以下內容
library lib;
part 'test.dart';
以下程式碼會產生此診斷訊息,因為 part of
指令使用程式庫的名稱,而非其所屬程式庫的 URI
part of lib;
常見修正方式
#使用 URI 來參照程式庫
part of 'lib.dart';
使用_super_參數
#參數 '{0}' 可以是 super 參數。
參數 '{0}' 可以是 super 參數。
描述
#當建構子的參數傳遞給 super 建構子,而未被參照或修改,且未使用 super
參數時,分析器會產生此診斷訊息。
範例
#以下程式碼會產生此診斷訊息,因為 B
的建構子的參數僅用作 super 建構子的引數
class A {
A({int? x, int? y});
}
class B extends A {
B({int? x, int? y}) : super(x: x, y: y);
}
常見修正方式
#使用 super
參數來傳遞引數
class A {
A({int? x, int? y});
}
class B extends A {
B({super.x, super.y});
}
使用_截斷_除法
#使用截斷除法。
描述
#當將兩個數字相除的結果使用 toInt
轉換為整數時,分析器會產生此診斷訊息。
Dart 有內建的整數除法運算子,既更有效率又更簡潔。
範例
#以下程式碼會產生此診斷,因為除以 x
和 y
的結果使用 toInt
轉換為整數
int divide(int x, int y) => (x / y).toInt();
常見修正方式
#使用整數除法運算子 (~/
)
int divide(int x, int y) => x ~/ y;
有效的_正規表示式
#無效的正規表示式語法。
描述
#當傳遞給類別 RegExp
的預設建構子的字串不包含有效的正規表示式時,分析器會產生此診斷訊息。
使用無效語法建立的正規表示式會在執行階段擲回 FormatException
。
範例
#以下程式碼會產生此診斷訊息,因為正規表示式無效
var r = RegExp(r'(');
常見修正方式
#修正正規表示式
var r = RegExp(r'\(');
void_檢查
#指派給 'void' 類型的變數。
描述
#當值指派給 void
類型的變數時,分析器會產生此診斷訊息。
無法存取此類變數的值,因此指派沒有任何意義。
範例
#以下程式碼會產生此診斷訊息,因為欄位 value
的類型為 void
,但正在將值指派給它
class A<T> {
T? value;
}
void f(A<void> a) {
a.value = 1;
}
以下程式碼會產生此診斷訊息,因為方法 m
中參數 p
的類型為 void
,但在調用中正在將值指派給它
class A<T> {
void m(T p) { }
}
void f(A<void> a) {
a.m(1);
}
常見修正方式
#如果變數的類型不正確,則變更變數的類型
class A<T> {
T? value;
}
void f(A<int> a) {
a.value = 1;
}
如果變數的類型正確,則移除指派
class A<T> {
T? value;
}
void f(A<void> a) {}
除非另有說明,否則本網站上的文件反映 Dart 3.7.1 版本。頁面最後更新於 2025-03-07。 檢視原始碼 或 回報問題。